sequel 2.2.0 → 2.3.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 (98) hide show
  1. data/CHANGELOG +1551 -4
  2. data/README +306 -19
  3. data/Rakefile +84 -56
  4. data/bin/sequel +106 -0
  5. data/doc/cheat_sheet.rdoc +225 -0
  6. data/doc/dataset_filtering.rdoc +182 -0
  7. data/lib/sequel_core.rb +136 -0
  8. data/lib/sequel_core/adapters/adapter_skeleton.rb +54 -0
  9. data/lib/sequel_core/adapters/ado.rb +80 -0
  10. data/lib/sequel_core/adapters/db2.rb +148 -0
  11. data/lib/sequel_core/adapters/dbi.rb +117 -0
  12. data/lib/sequel_core/adapters/informix.rb +78 -0
  13. data/lib/sequel_core/adapters/jdbc.rb +186 -0
  14. data/lib/sequel_core/adapters/jdbc/mysql.rb +55 -0
  15. data/lib/sequel_core/adapters/jdbc/postgresql.rb +66 -0
  16. data/lib/sequel_core/adapters/jdbc/sqlite.rb +47 -0
  17. data/lib/sequel_core/adapters/mysql.rb +231 -0
  18. data/lib/sequel_core/adapters/odbc.rb +155 -0
  19. data/lib/sequel_core/adapters/odbc_mssql.rb +106 -0
  20. data/lib/sequel_core/adapters/openbase.rb +64 -0
  21. data/lib/sequel_core/adapters/oracle.rb +170 -0
  22. data/lib/sequel_core/adapters/postgres.rb +199 -0
  23. data/lib/sequel_core/adapters/shared/mysql.rb +275 -0
  24. data/lib/sequel_core/adapters/shared/postgres.rb +351 -0
  25. data/lib/sequel_core/adapters/shared/sqlite.rb +146 -0
  26. data/lib/sequel_core/adapters/sqlite.rb +138 -0
  27. data/lib/sequel_core/connection_pool.rb +194 -0
  28. data/lib/sequel_core/core_ext.rb +203 -0
  29. data/lib/sequel_core/core_sql.rb +184 -0
  30. data/lib/sequel_core/database.rb +471 -0
  31. data/lib/sequel_core/database/schema.rb +156 -0
  32. data/lib/sequel_core/dataset.rb +457 -0
  33. data/lib/sequel_core/dataset/callback.rb +13 -0
  34. data/lib/sequel_core/dataset/convenience.rb +245 -0
  35. data/lib/sequel_core/dataset/pagination.rb +96 -0
  36. data/lib/sequel_core/dataset/query.rb +41 -0
  37. data/lib/sequel_core/dataset/schema.rb +15 -0
  38. data/lib/sequel_core/dataset/sql.rb +889 -0
  39. data/lib/sequel_core/deprecated.rb +26 -0
  40. data/lib/sequel_core/exceptions.rb +42 -0
  41. data/lib/sequel_core/migration.rb +187 -0
  42. data/lib/sequel_core/object_graph.rb +216 -0
  43. data/lib/sequel_core/pretty_table.rb +71 -0
  44. data/lib/sequel_core/schema.rb +2 -0
  45. data/lib/sequel_core/schema/generator.rb +239 -0
  46. data/lib/sequel_core/schema/sql.rb +325 -0
  47. data/lib/sequel_core/sql.rb +812 -0
  48. data/lib/sequel_model.rb +5 -1
  49. data/lib/sequel_model/association_reflection.rb +3 -8
  50. data/lib/sequel_model/base.rb +15 -10
  51. data/lib/sequel_model/inflector.rb +3 -5
  52. data/lib/sequel_model/plugins.rb +1 -1
  53. data/lib/sequel_model/record.rb +11 -3
  54. data/lib/sequel_model/schema.rb +4 -4
  55. data/lib/sequel_model/validations.rb +6 -1
  56. data/spec/adapters/ado_spec.rb +17 -0
  57. data/spec/adapters/informix_spec.rb +96 -0
  58. data/spec/adapters/mysql_spec.rb +764 -0
  59. data/spec/adapters/oracle_spec.rb +222 -0
  60. data/spec/adapters/postgres_spec.rb +441 -0
  61. data/spec/adapters/spec_helper.rb +7 -0
  62. data/spec/adapters/sqlite_spec.rb +400 -0
  63. data/spec/integration/dataset_test.rb +51 -0
  64. data/spec/integration/eager_loader_test.rb +702 -0
  65. data/spec/integration/schema_test.rb +102 -0
  66. data/spec/integration/spec_helper.rb +44 -0
  67. data/spec/integration/type_test.rb +43 -0
  68. data/spec/rcov.opts +2 -0
  69. data/spec/sequel_core/connection_pool_spec.rb +363 -0
  70. data/spec/sequel_core/core_ext_spec.rb +156 -0
  71. data/spec/sequel_core/core_sql_spec.rb +427 -0
  72. data/spec/sequel_core/database_spec.rb +964 -0
  73. data/spec/sequel_core/dataset_spec.rb +2977 -0
  74. data/spec/sequel_core/expression_filters_spec.rb +346 -0
  75. data/spec/sequel_core/migration_spec.rb +261 -0
  76. data/spec/sequel_core/object_graph_spec.rb +234 -0
  77. data/spec/sequel_core/pretty_table_spec.rb +58 -0
  78. data/spec/sequel_core/schema_generator_spec.rb +122 -0
  79. data/spec/sequel_core/schema_spec.rb +497 -0
  80. data/spec/sequel_core/spec_helper.rb +51 -0
  81. data/spec/{association_reflection_spec.rb → sequel_model/association_reflection_spec.rb} +6 -6
  82. data/spec/{associations_spec.rb → sequel_model/associations_spec.rb} +47 -18
  83. data/spec/{base_spec.rb → sequel_model/base_spec.rb} +2 -1
  84. data/spec/{caching_spec.rb → sequel_model/caching_spec.rb} +0 -0
  85. data/spec/{dataset_methods_spec.rb → sequel_model/dataset_methods_spec.rb} +13 -1
  86. data/spec/{eager_loading_spec.rb → sequel_model/eager_loading_spec.rb} +75 -14
  87. data/spec/{hooks_spec.rb → sequel_model/hooks_spec.rb} +4 -4
  88. data/spec/sequel_model/inflector_spec.rb +119 -0
  89. data/spec/{model_spec.rb → sequel_model/model_spec.rb} +30 -11
  90. data/spec/{plugins_spec.rb → sequel_model/plugins_spec.rb} +0 -0
  91. data/spec/{record_spec.rb → sequel_model/record_spec.rb} +47 -6
  92. data/spec/{schema_spec.rb → sequel_model/schema_spec.rb} +18 -4
  93. data/spec/{spec_helper.rb → sequel_model/spec_helper.rb} +3 -2
  94. data/spec/{validations_spec.rb → sequel_model/validations_spec.rb} +37 -17
  95. data/spec/spec_config.rb +9 -0
  96. data/spec/spec_config.rb.example +10 -0
  97. metadata +110 -37
  98. data/spec/inflector_spec.rb +0 -34
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ unless Object.const_defined?('Sequel')
3
+ $:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
4
+ require 'sequel_core'
5
+ Sequel.quote_identifiers = false
6
+ end
7
+ require File.join(File.dirname(__FILE__), '../spec_config.rb')
@@ -0,0 +1,400 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper.rb')
2
+
3
+ unless defined?(SQLITE_DB)
4
+ SQLITE_URL = 'sqlite:/' unless defined? SQLITE_URL
5
+ SQLITE_DB = Sequel.connect(ENV['SEQUEL_SQLITE_SPEC_DB']||SQLITE_URL)
6
+ end
7
+
8
+ context "An SQLite database" do
9
+ before do
10
+ @db = SQLITE_DB
11
+ end
12
+
13
+ if SQLITE_DB.auto_vacuum == :none
14
+ specify "should support getting pragma values" do
15
+ @db.pragma_get(:auto_vacuum).to_s.should == '0'
16
+ end
17
+
18
+ specify "should support setting pragma values" do
19
+ @db.pragma_set(:auto_vacuum, '1')
20
+ @db.pragma_get(:auto_vacuum).to_s.should == '1'
21
+ @db.pragma_set(:auto_vacuum, '2')
22
+ @db.pragma_get(:auto_vacuum).to_s.should == '2'
23
+ end
24
+
25
+ specify "should support getting and setting the auto_vacuum pragma" do
26
+ @db.auto_vacuum = :full
27
+ @db.auto_vacuum.should == :full
28
+ @db.auto_vacuum = :incremental
29
+ @db.auto_vacuum.should == :incremental
30
+
31
+ proc {@db.auto_vacuum = :invalid}.should raise_error(Sequel::Error)
32
+ end
33
+ end
34
+
35
+ specify "should provide a list of existing tables" do
36
+ @db.drop_table(:testing) rescue nil
37
+ @db.tables.should be_a_kind_of(Array)
38
+ @db.tables.should_not include(:testing)
39
+ @db.create_table! :testing do
40
+ text :name
41
+ end
42
+ @db.tables.should include(:testing)
43
+ end
44
+
45
+ specify "should support getting and setting the synchronous pragma" do
46
+ @db.synchronous = :off
47
+ @db.synchronous.should == :off
48
+ @db.synchronous = :normal
49
+ @db.synchronous.should == :normal
50
+ @db.synchronous = :full
51
+ @db.synchronous.should == :full
52
+
53
+ proc {@db.synchronous = :invalid}.should raise_error(Sequel::Error)
54
+ end
55
+
56
+ specify "should support getting and setting the temp_store pragma" do
57
+ @db.temp_store = :default
58
+ @db.temp_store.should == :default
59
+ @db.temp_store = :file
60
+ @db.temp_store.should == :file
61
+ @db.temp_store = :memory
62
+ @db.temp_store.should == :memory
63
+
64
+ proc {@db.temp_store = :invalid}.should raise_error(Sequel::Error)
65
+ end
66
+
67
+ specify "should be able to execute transactions" do
68
+ @db.transaction do
69
+ @db.create_table!(:t) {text :name}
70
+ end
71
+
72
+ @db.tables.should include(:t)
73
+
74
+ proc {@db.transaction do
75
+ @db.create_table!(:u) {text :name}
76
+ raise ArgumentError
77
+ end}.should raise_error(ArgumentError)
78
+ # no commit
79
+ @db.tables.should_not include(:u)
80
+
81
+ proc {@db.transaction do
82
+ @db.create_table!(:v) {text :name}
83
+ raise Sequel::Error::Rollback
84
+ end}.should_not raise_error
85
+ # no commit
86
+ @db.tables.should_not include(:r)
87
+ end
88
+
89
+ specify "should support nested transactions" do
90
+ @db.transaction do
91
+ @db.transaction do
92
+ @db.create_table!(:t) {text :name}
93
+ end
94
+ end
95
+
96
+ @db.tables.should include(:t)
97
+
98
+ proc {@db.transaction do
99
+ @db.create_table!(:v) {text :name}
100
+ @db.transaction do
101
+ raise Sequel::Error::Rollback # should roll back the top-level transaction
102
+ end
103
+ end}.should_not raise_error
104
+ # no commit
105
+ @db.tables.should_not include(:v)
106
+ end
107
+
108
+ specify "should handle returning inside of transaction by committing" do
109
+ @db.create_table!(:items2){text :name}
110
+ def @db.ret_commit
111
+ transaction do
112
+ self[:items2] << {:name => 'abc'}
113
+ return
114
+ self[:items2] << {:name => 'd'}
115
+ end
116
+ end
117
+ @db[:items2].count.should == 0
118
+ @db.ret_commit
119
+ @db[:items2].count.should == 1
120
+ @db.ret_commit
121
+ @db[:items2].count.should == 2
122
+ proc do
123
+ @db.transaction do
124
+ raise Interrupt, 'asdf'
125
+ end
126
+ end.should raise_error(Interrupt)
127
+
128
+ @db[:items2].count.should == 2
129
+ end
130
+
131
+ specify "should support timestamps" do
132
+ t1 = Time.at(Time.now.to_i) #normalize time
133
+ @db.create_table!(:time) {timestamp :t}
134
+ @db[:time] << {:t => t1}
135
+ x = @db[:time].first[:t]
136
+ [t1.iso8601, t1.to_s].should include(x.respond_to?(:iso8601) ? x.iso8601 : x.to_s)
137
+ end
138
+
139
+ specify "should support sequential primary keys" do
140
+ @db.create_table!(:with_pk) {primary_key :id; text :name}
141
+ @db[:with_pk] << {:name => 'abc'}
142
+ @db[:with_pk] << {:name => 'def'}
143
+ @db[:with_pk] << {:name => 'ghi'}
144
+ @db[:with_pk].order(:name).all.should == [
145
+ {:id => 1, :name => 'abc'},
146
+ {:id => 2, :name => 'def'},
147
+ {:id => 3, :name => 'ghi'}
148
+ ]
149
+ end
150
+
151
+ specify "should catch invalid SQL errors and raise them as Error" do
152
+ proc {@db.execute 'blah blah'}.should raise_error(Sequel::Error)
153
+ proc {@db.execute_insert 'blah blah'}.should raise_error(Sequel::Error)
154
+ end
155
+
156
+ specify "should not swallow non-SQLite based exceptions" do
157
+ proc {@db.pool.hold{raise Interrupt, "test"}}.should raise_error(Interrupt)
158
+ end
159
+
160
+ specify "should correctly parse the schema" do
161
+ @db.create_table!(:time2) {timestamp :t}
162
+ @db.schema(:time2, :reload=>true).should == [[:t, {:type=>:datetime, :allow_null=>true, :max_chars=>nil, :default=>nil, :db_type=>"timestamp", :numeric_precision=>nil, :primary_key=>false}]]
163
+ end
164
+
165
+ specify "should get the schema all database tables if no table name is used" do
166
+ @db.create_table!(:time2) {timestamp :t}
167
+ @db.schema(:time2, :reload=>true).should == @db.schema(nil, :reload=>true)[:time]
168
+ end
169
+ end
170
+
171
+ context "An SQLite dataset" do
172
+ setup do
173
+ SQLITE_DB.create_table! :items do
174
+ integer :id, :primary_key => true, :auto_increment => true
175
+ text :name
176
+ float :value
177
+ end
178
+ @d = SQLITE_DB[:items]
179
+ @d.delete # remove all records
180
+ end
181
+
182
+ specify "should return the correct records" do
183
+ @d.to_a.should == []
184
+ @d << {:name => 'abc', :value => 1.23}
185
+ @d << {:name => 'abc', :value => 4.56}
186
+ @d << {:name => 'def', :value => 7.89}
187
+ @d.select(:name, :value).to_a.sort_by {|h| h[:value]}.should == [
188
+ {:name => 'abc', :value => 1.23},
189
+ {:name => 'abc', :value => 4.56},
190
+ {:name => 'def', :value => 7.89}
191
+ ]
192
+ end
193
+
194
+ specify "should return the correct record count" do
195
+ @d.count.should == 0
196
+ @d << {:name => 'abc', :value => 1.23}
197
+ @d << {:name => 'abc', :value => 4.56}
198
+ @d << {:name => 'def', :value => 7.89}
199
+ @d.count.should == 3
200
+ end
201
+
202
+ specify "should return the last inserted id when inserting records" do
203
+ id = @d << {:name => 'abc', :value => 1.23}
204
+ id.should == @d.first[:id]
205
+ end
206
+
207
+ specify "should update records correctly" do
208
+ @d << {:name => 'abc', :value => 1.23}
209
+ @d << {:name => 'abc', :value => 4.56}
210
+ @d << {:name => 'def', :value => 7.89}
211
+ @d.filter(:name => 'abc').update(:value => 5.3)
212
+
213
+ # the third record should stay the same
214
+ @d[:name => 'def'][:value].should == 7.89
215
+ @d.filter(:value => 5.3).count.should == 2
216
+ end
217
+
218
+ specify "should delete records correctly" do
219
+ @d << {:name => 'abc', :value => 1.23}
220
+ @d << {:name => 'abc', :value => 4.56}
221
+ @d << {:name => 'def', :value => 7.89}
222
+ @d.filter(:name => 'abc').delete
223
+
224
+ @d.count.should == 1
225
+ @d.first[:name].should == 'def'
226
+ end
227
+
228
+ specify "should handle string pattern matches correctly" do
229
+ @d.literal(:x.like('a')).should == "(x LIKE 'a')"
230
+ @d.literal(~:x.like('a')).should == "NOT (x LIKE 'a')"
231
+ @d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
232
+ @d.literal(~:x.ilike('a')).should == "NOT (x LIKE 'a')"
233
+ end
234
+
235
+ specify "should raise errors if given a regexp pattern match" do
236
+ proc{@d.literal(:x.like(/a/))}.should raise_error(Sequel::Error)
237
+ proc{@d.literal(~:x.like(/a/))}.should raise_error(Sequel::Error)
238
+ proc{@d.literal(:x.like(/a/i))}.should raise_error(Sequel::Error)
239
+ proc{@d.literal(~:x.like(/a/i))}.should raise_error(Sequel::Error)
240
+ end
241
+ end
242
+
243
+ context "An SQLite dataset" do
244
+ setup do
245
+ SQLITE_DB.create_table! :items do
246
+ integer :id, :primary_key => true, :auto_increment => true
247
+ text :name
248
+ float :value
249
+ end
250
+ @d = SQLITE_DB[:items]
251
+ @d.delete # remove all records
252
+ @d << {:name => 'abc', :value => 1.23}
253
+ @d << {:name => 'def', :value => 4.56}
254
+ @d << {:name => 'ghi', :value => 7.89}
255
+ end
256
+
257
+ specify "should correctly return avg" do
258
+ @d.avg(:value).to_s.should == ((1.23 + 4.56 + 7.89) / 3).to_s
259
+ end
260
+
261
+ specify "should correctly return sum" do
262
+ @d.sum(:value).to_s.should == (1.23 + 4.56 + 7.89).to_s
263
+ end
264
+
265
+ specify "should correctly return max" do
266
+ @d.max(:value).to_s.should == 7.89.to_s
267
+ end
268
+
269
+ specify "should correctly return min" do
270
+ @d.min(:value).to_s.should == 1.23.to_s
271
+ end
272
+ end
273
+
274
+ context "SQLite::Dataset#delete" do
275
+ setup do
276
+ SQLITE_DB.create_table! :items do
277
+ integer :id, :primary_key => true, :auto_increment => true
278
+ text :name
279
+ float :value
280
+ end
281
+ @d = SQLITE_DB[:items]
282
+ @d.delete # remove all records
283
+ @d << {:name => 'abc', :value => 1.23}
284
+ @d << {:name => 'def', :value => 4.56}
285
+ @d << {:name => 'ghi', :value => 7.89}
286
+ end
287
+
288
+ specify "should return the number of records affected when filtered" do
289
+ @d.count.should == 3
290
+ @d.filter {:value < 3}.delete.should == 1
291
+ @d.count.should == 2
292
+
293
+ @d.filter {:value < 3}.delete.should == 0
294
+ @d.count.should == 2
295
+ end
296
+
297
+ specify "should return the number of records affected when unfiltered" do
298
+ @d.count.should == 3
299
+ @d.delete.should == 3
300
+ @d.count.should == 0
301
+
302
+ @d.delete.should == 0
303
+ end
304
+ end
305
+
306
+ context "SQLite::Dataset#update" do
307
+ setup do
308
+ SQLITE_DB.create_table! :items do
309
+ integer :id, :primary_key => true, :auto_increment => true
310
+ text :name
311
+ float :value
312
+ end
313
+ @d = SQLITE_DB[:items]
314
+ @d.delete # remove all records
315
+ @d << {:name => 'abc', :value => 1.23}
316
+ @d << {:name => 'def', :value => 4.56}
317
+ @d << {:name => 'ghi', :value => 7.89}
318
+ end
319
+
320
+ specify "should return the number of records affected" do
321
+ @d.filter(:name => 'abc').update(:value => 2).should == 1
322
+
323
+ @d.update(:value => 10).should == 3
324
+
325
+ @d.filter(:name => 'xxx').update(:value => 23).should == 0
326
+ end
327
+ end
328
+
329
+ context "SQLite dataset" do
330
+ setup do
331
+ SQLITE_DB.create_table! :test do
332
+ integer :id, :primary_key => true, :auto_increment => true
333
+ text :name
334
+ float :value
335
+ end
336
+ SQLITE_DB.create_table! :items do
337
+ integer :id, :primary_key => true, :auto_increment => true
338
+ text :name
339
+ float :value
340
+ end
341
+ @d = SQLITE_DB[:items]
342
+ @d.delete # remove all records
343
+ @d << {:name => 'abc', :value => 1.23}
344
+ @d << {:name => 'def', :value => 4.56}
345
+ @d << {:name => 'ghi', :value => 7.89}
346
+ end
347
+
348
+ teardown do
349
+ SQLITE_DB.drop_table :test
350
+ end
351
+
352
+ specify "should be able to insert from a subquery" do
353
+ SQLITE_DB[:test] << @d
354
+ SQLITE_DB[:test].count.should == 3
355
+ SQLITE_DB[:test].select(:name, :value).order(:value).to_a.should == \
356
+ @d.select(:name, :value).order(:value).to_a
357
+ end
358
+ end
359
+
360
+ context "A SQLite database" do
361
+ setup do
362
+ @db = SQLITE_DB
363
+ @db.create_table! :test2 do
364
+ text :name
365
+ integer :value
366
+ end
367
+ end
368
+
369
+ specify "should support add_column operations" do
370
+ @db.add_column :test2, :xyz, :text
371
+
372
+ @db[:test2].columns.should == [:name, :value, :xyz]
373
+ @db[:test2] << {:name => 'mmm', :value => 111, :xyz=>'000'}
374
+ @db[:test2].first.should == {:name => 'mmm', :value => 111, :xyz=>'000'}
375
+ end
376
+
377
+ specify "should support drop_column operations" do
378
+ @db.drop_column :test2, :value
379
+ @db[:test2].columns.should == [:name]
380
+ @db[:test2] << {:name => 'mmm'}
381
+ @db[:test2].first.should == {:name => 'mmm'}
382
+ end
383
+
384
+ specify "should not support rename_column operations" do
385
+ proc {@db.rename_column :test2, :value, :zyx}.should raise_error(Sequel::Error)
386
+ end
387
+
388
+ specify "should not support set_column_type operations" do
389
+ proc {@db.set_column_type :test2, :value, :integer}.should raise_error(Sequel::Error)
390
+ end
391
+
392
+ specify "should support add_index" do
393
+ @db.add_index :test2, :value, :unique => true
394
+ @db.add_index :test2, [:name, :value]
395
+ end
396
+
397
+ specify "should not support drop_index" do
398
+ proc {@db.drop_index :test2, :value}.should raise_error(Sequel::Error)
399
+ end
400
+ end
@@ -0,0 +1,51 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper.rb')
2
+
3
+ describe "Simple Dataset operations" do
4
+ before do
5
+ INTEGRATION_DB.create_table!(:items) do
6
+ primary_key :id
7
+ integer :number
8
+ end
9
+ @ds = INTEGRATION_DB[:items]
10
+ @ds.insert(:number=>10)
11
+ clear_sqls
12
+ end
13
+ after do
14
+ INTEGRATION_DB.drop_table(:items)
15
+ end
16
+
17
+ specify "should insert with a primary key specified" do
18
+ @ds.insert(:id=>100, :number=>20)
19
+ sqls_should_be(/INSERT INTO items \((number, id|id, number)\) VALUES \((100, 20|20, 100)\)/)
20
+ @ds.count.should == 2
21
+ @ds.order(:id).all.should == [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
22
+ end
23
+
24
+ specify "should have insert return primary key value" do
25
+ @ds.insert(:number=>20).should == 2
26
+ sqls_should_be('INSERT INTO items (number) VALUES (20)')
27
+ @ds.filter(:id=>2).first[:number].should == 20
28
+ end
29
+
30
+ specify "should delete correctly" do
31
+ @ds.filter(1=>1).delete.should == 1
32
+ sqls_should_be('DELETE FROM items WHERE (1 = 1)')
33
+ @ds.count.should == 0
34
+ end
35
+
36
+ specify "should update correctly" do
37
+ @ds.update(:number=>:number+1).should == 1
38
+ sqls_should_be('UPDATE items SET number = (number + 1)')
39
+ @ds.all.should == [{:id=>1, :number=>11}]
40
+ end
41
+
42
+ specify "should fetch all results correctly" do
43
+ @ds.all.should == [{:id=>1, :number=>10}]
44
+ sqls_should_be('SELECT * FROM items')
45
+ end
46
+
47
+ specify "should fetch a single row correctly" do
48
+ @ds.first.should == {:id=>1, :number=>10}
49
+ sqls_should_be('SELECT * FROM items LIMIT 1')
50
+ end
51
+ end