sequel 0.5.0.2 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/COPYING +18 -18
  2. data/Rakefile +17 -98
  3. data/lib/sequel.rb +2 -71
  4. metadata +10 -108
  5. data/CHANGELOG +0 -989
  6. data/bin/sequel +0 -41
  7. data/lib/sequel/adapters/adapter_skeleton.rb +0 -68
  8. data/lib/sequel/adapters/ado.rb +0 -100
  9. data/lib/sequel/adapters/db2.rb +0 -158
  10. data/lib/sequel/adapters/dbi.rb +0 -126
  11. data/lib/sequel/adapters/informix.rb +0 -87
  12. data/lib/sequel/adapters/jdbc.rb +0 -108
  13. data/lib/sequel/adapters/mysql.rb +0 -269
  14. data/lib/sequel/adapters/odbc.rb +0 -145
  15. data/lib/sequel/adapters/odbc_mssql.rb +0 -93
  16. data/lib/sequel/adapters/openbase.rb +0 -90
  17. data/lib/sequel/adapters/oracle.rb +0 -99
  18. data/lib/sequel/adapters/postgres.rb +0 -519
  19. data/lib/sequel/adapters/sqlite.rb +0 -192
  20. data/lib/sequel/ado.rb +0 -6
  21. data/lib/sequel/array_keys.rb +0 -296
  22. data/lib/sequel/connection_pool.rb +0 -152
  23. data/lib/sequel/core_ext.rb +0 -59
  24. data/lib/sequel/core_sql.rb +0 -191
  25. data/lib/sequel/database.rb +0 -433
  26. data/lib/sequel/dataset.rb +0 -409
  27. data/lib/sequel/dataset/convenience.rb +0 -321
  28. data/lib/sequel/dataset/sequelizer.rb +0 -354
  29. data/lib/sequel/dataset/sql.rb +0 -586
  30. data/lib/sequel/db2.rb +0 -6
  31. data/lib/sequel/dbi.rb +0 -6
  32. data/lib/sequel/exceptions.rb +0 -45
  33. data/lib/sequel/informix.rb +0 -6
  34. data/lib/sequel/migration.rb +0 -191
  35. data/lib/sequel/model.rb +0 -8
  36. data/lib/sequel/mysql.rb +0 -6
  37. data/lib/sequel/odbc.rb +0 -6
  38. data/lib/sequel/oracle.rb +0 -6
  39. data/lib/sequel/postgres.rb +0 -6
  40. data/lib/sequel/pretty_table.rb +0 -73
  41. data/lib/sequel/schema.rb +0 -8
  42. data/lib/sequel/schema/schema_generator.rb +0 -131
  43. data/lib/sequel/schema/schema_sql.rb +0 -131
  44. data/lib/sequel/sqlite.rb +0 -6
  45. data/lib/sequel/worker.rb +0 -58
  46. data/spec/adapters/informix_spec.rb +0 -139
  47. data/spec/adapters/mysql_spec.rb +0 -330
  48. data/spec/adapters/oracle_spec.rb +0 -130
  49. data/spec/adapters/postgres_spec.rb +0 -189
  50. data/spec/adapters/sqlite_spec.rb +0 -345
  51. data/spec/array_keys_spec.rb +0 -679
  52. data/spec/connection_pool_spec.rb +0 -356
  53. data/spec/core_ext_spec.rb +0 -67
  54. data/spec/core_sql_spec.rb +0 -301
  55. data/spec/database_spec.rb +0 -811
  56. data/spec/dataset_spec.rb +0 -2381
  57. data/spec/migration_spec.rb +0 -261
  58. data/spec/pretty_table_spec.rb +0 -66
  59. data/spec/rcov.opts +0 -4
  60. data/spec/schema_generator_spec.rb +0 -86
  61. data/spec/schema_spec.rb +0 -230
  62. data/spec/sequel_spec.rb +0 -10
  63. data/spec/sequelizer_spec.rb +0 -389
  64. data/spec/spec.opts +0 -5
  65. data/spec/spec_helper.rb +0 -44
  66. data/spec/worker_spec.rb +0 -96
data/spec/dataset_spec.rb DELETED
@@ -1,2381 +0,0 @@
1
- require File.join(File.dirname(__FILE__), "spec_helper")
2
-
3
- context "Dataset" do
4
- setup do
5
- @dataset = Sequel::Dataset.new("db")
6
- end
7
-
8
- specify "should accept database and opts in initialize" do
9
- db = "db"
10
- opts = {:from => :test}
11
- d = Sequel::Dataset.new(db, opts)
12
- d.db.should be(db)
13
- d.opts.should be(opts)
14
-
15
- d = Sequel::Dataset.new(db)
16
- d.db.should be(db)
17
- d.opts.should be_a_kind_of(Hash)
18
- d.opts.should == {}
19
- end
20
-
21
- specify "should provide clone_merge for chainability." do
22
- d1 = @dataset.clone_merge(:from => :test)
23
- d1.class.should == @dataset.class
24
- d1.should_not == @dataset
25
- d1.db.should be(@dataset.db)
26
- d1.opts[:from].should == :test
27
- @dataset.opts[:from].should be_nil
28
-
29
- d2 = d1.clone_merge(:order => :name)
30
- d2.class.should == @dataset.class
31
- d2.should_not == d1
32
- d2.should_not == @dataset
33
- d2.db.should be(@dataset.db)
34
- d2.opts[:from].should == :test
35
- d2.opts[:order].should == :name
36
- d1.opts[:order].should be_nil
37
- end
38
-
39
- specify "should include Enumerable" do
40
- Sequel::Dataset.included_modules.should include(Enumerable)
41
- end
42
-
43
- specify "should raise ImplementedError for the dataset interface methods" do
44
- proc {@dataset.fetch_rows('abc')}.should raise_error(NotImplementedError)
45
- proc {@dataset.insert(1, 2, 3)}.should raise_error(NotImplementedError)
46
- proc {@dataset.update(:name => 'abc')}.should raise_error(NotImplementedError)
47
- proc {@dataset.delete}.should raise_error(NotImplementedError)
48
- end
49
- end
50
-
51
- context "Dataset#clone_merge" do
52
- setup do
53
- @dataset = Sequel::Dataset.new(nil).from(:items)
54
- end
55
-
56
- specify "should return a clone self" do
57
- clone = @dataset.clone_merge({})
58
- clone.class.should == @dataset.class
59
- clone.db.should == @dataset.db
60
- clone.opts.should == @dataset.opts
61
- end
62
-
63
- specify "should merge the specified options" do
64
- clone = @dataset.clone_merge(1 => 2)
65
- clone.opts.should == {1 => 2, :from => [:items]}
66
- end
67
-
68
- specify "should overwrite existing options" do
69
- clone = @dataset.clone_merge(:from => [:other])
70
- clone.opts.should == {:from => [:other]}
71
- end
72
-
73
- specify "should create a clone with a deep copy of options" do
74
- clone = @dataset.clone_merge(:from => [:other])
75
- @dataset.opts[:from].should == [:items]
76
- clone.opts[:from].should == [:other]
77
- end
78
-
79
- specify "should return an object with the same modules included" do
80
- m = Module.new do
81
- def __xyz__; "xyz"; end
82
- end
83
- @dataset.extend(m)
84
- @dataset.clone_merge({}).should respond_to(:__xyz__)
85
- end
86
- end
87
-
88
- context "A simple dataset" do
89
- setup do
90
- @dataset = Sequel::Dataset.new(nil).from(:test)
91
- end
92
-
93
- specify "should format a select statement" do
94
- @dataset.select_sql.should == 'SELECT * FROM test'
95
- end
96
-
97
- specify "should format a delete statement" do
98
- @dataset.delete_sql.should == 'DELETE FROM test'
99
- end
100
-
101
- specify "should format an insert statement with default values" do
102
- @dataset.insert_sql.should == 'INSERT INTO test DEFAULT VALUES'
103
- end
104
-
105
- specify "should format an insert statement with hash" do
106
- @dataset.insert_sql(:name => 'wxyz', :price => 342).
107
- should match(/INSERT INTO test \(name, price\) VALUES \('wxyz', 342\)|INSERT INTO test \(price, name\) VALUES \(342, 'wxyz'\)/)
108
-
109
- @dataset.insert_sql({}).should == "INSERT INTO test DEFAULT VALUES"
110
- end
111
-
112
- specify "should format an insert statement with array with keys" do
113
- v = [1, 2, 3]
114
- v.keys = [:a, :b, :c]
115
- @dataset.insert_sql(v).should == "INSERT INTO test (a, b, c) VALUES (1, 2, 3)"
116
-
117
- v = []
118
- v.keys = [:a, :b]
119
- @dataset.insert_sql(v).should == "INSERT INTO test DEFAULT VALUES"
120
- end
121
-
122
- specify "should format an insert statement with string keys" do
123
- @dataset.insert_sql('name' => 'wxyz', 'price' => 342).
124
- should match(/INSERT INTO test \(name, price\) VALUES \('wxyz', 342\)|INSERT INTO test \(price, name\) VALUES \(342, 'wxyz'\)/)
125
- end
126
-
127
- specify "should format an insert statement with a model instance" do
128
- dbb = Sequel::Database.new
129
-
130
- @c = Class.new(Sequel::Model) do
131
- attr_accessor :values
132
- end
133
-
134
- v = @c.new; v.values = {:a => 1}
135
-
136
- @dataset.insert_sql(v).should == "INSERT INTO test (a) VALUES (1)"
137
-
138
- v = @c.new; v.values = {}
139
- @dataset.insert_sql(v).should == "INSERT INTO test DEFAULT VALUES"
140
- end
141
-
142
- specify "should format an insert statement with an arbitrary value" do
143
- @dataset.insert_sql(123).should == "INSERT INTO test VALUES (123)"
144
- end
145
-
146
- specify "should format an insert statement with sub-query" do
147
- @sub = Sequel::Dataset.new(nil).from(:something).filter(:x => 2)
148
- @dataset.insert_sql(@sub).should == \
149
- "INSERT INTO test (SELECT * FROM something WHERE (x = 2))"
150
- end
151
-
152
- specify "should format an insert statement with array" do
153
- @dataset.insert_sql('a', 2, 6.5).should ==
154
- "INSERT INTO test VALUES ('a', 2, 6.5)"
155
- end
156
-
157
- specify "should format an update statement" do
158
- @dataset.update_sql(:name => 'abc').should ==
159
- "UPDATE test SET name = 'abc'"
160
-
161
- @dataset.update_sql {:x << :y}.should ==
162
- "UPDATE test SET x = y"
163
- end
164
-
165
- specify "should format an update statement with array with keys" do
166
- v = ['abc']
167
- v.keys = [:name]
168
-
169
- @dataset.update_sql(v).should == "UPDATE test SET name = 'abc'"
170
- end
171
-
172
- specify "should be able to return rows for arbitrary SQL" do
173
- @dataset.select_sql(:sql => 'xxx yyy zzz').should ==
174
- "xxx yyy zzz"
175
- end
176
- end
177
-
178
- context "A dataset with multiple tables in its FROM clause" do
179
- setup do
180
- @dataset = Sequel::Dataset.new(nil).from(:t1, :t2)
181
- end
182
-
183
- specify "should raise on #update_sql" do
184
- proc {@dataset.update_sql(:a=>1)}.should raise_error
185
- end
186
-
187
- specify "should raise on #delete_sql" do
188
- proc {@dataset.delete_sql}.should raise_error
189
- end
190
-
191
- specify "should generate a select query FROM all specified tables" do
192
- @dataset.select_sql.should == "SELECT * FROM t1, t2"
193
- end
194
- end
195
-
196
- context "Dataset#where" do
197
- setup do
198
- @dataset = Sequel::Dataset.new(nil).from(:test)
199
- @d1 = @dataset.where(:region => 'Asia')
200
- @d2 = @dataset.where('(region = ?)', 'Asia')
201
- @d3 = @dataset.where("(a = 1)")
202
- end
203
-
204
- specify "should work with hashes" do
205
- @dataset.where(:name => 'xyz', :price => 342).select_sql.
206
- should match(/WHERE \(name = 'xyz'\) AND \(price = 342\)|WHERE \(price = 342\) AND \(name = 'xyz'\)/)
207
- end
208
-
209
- specify "should work with arrays (ala ActiveRecord)" do
210
- @dataset.where('price < ? AND id in (?)', 100, [1, 2, 3]).select_sql.should ==
211
- "SELECT * FROM test WHERE price < 100 AND id in (1, 2, 3)"
212
- end
213
-
214
- specify "should work with strings (custom SQL expressions)" do
215
- @dataset.where('(a = 1 AND b = 2)').select_sql.should ==
216
- "SELECT * FROM test WHERE (a = 1 AND b = 2)"
217
- end
218
-
219
- specify "should affect select, delete and update statements" do
220
- @d1.select_sql.should == "SELECT * FROM test WHERE (region = 'Asia')"
221
- @d1.delete_sql.should == "DELETE FROM test WHERE (region = 'Asia')"
222
- @d1.update_sql(:GDP => 0).should == "UPDATE test SET GDP = 0 WHERE (region = 'Asia')"
223
-
224
- @d2.select_sql.should == "SELECT * FROM test WHERE (region = 'Asia')"
225
- @d2.delete_sql.should == "DELETE FROM test WHERE (region = 'Asia')"
226
- @d2.update_sql(:GDP => 0).should == "UPDATE test SET GDP = 0 WHERE (region = 'Asia')"
227
-
228
- @d3.select_sql.should == "SELECT * FROM test WHERE (a = 1)"
229
- @d3.delete_sql.should == "DELETE FROM test WHERE (a = 1)"
230
- @d3.update_sql(:GDP => 0).should == "UPDATE test SET GDP = 0 WHERE (a = 1)"
231
-
232
- end
233
-
234
- specify "should be composable using AND operator (for scoping)" do
235
- # hashes are merged, no problem
236
- @d1.where(:size => 'big').select_sql.should ==
237
- "SELECT * FROM test WHERE (region = 'Asia') AND (size = 'big')"
238
-
239
- # hash and string
240
- @d1.where('population > 1000').select_sql.should ==
241
- "SELECT * FROM test WHERE (region = 'Asia') AND (population > 1000)"
242
- @d1.where('(a > 1) OR (b < 2)').select_sql.should ==
243
- "SELECT * FROM test WHERE (region = 'Asia') AND ((a > 1) OR (b < 2))"
244
-
245
- # hash and array
246
- @d1.where('(GDP > ?)', 1000).select_sql.should ==
247
- "SELECT * FROM test WHERE (region = 'Asia') AND (GDP > 1000)"
248
-
249
- # array and array
250
- @d2.where('(GDP > ?)', 1000).select_sql.should ==
251
- "SELECT * FROM test WHERE (region = 'Asia') AND (GDP > 1000)"
252
-
253
- # array and hash
254
- @d2.where(:name => ['Japan', 'China']).select_sql.should ==
255
- "SELECT * FROM test WHERE (region = 'Asia') AND (name IN ('Japan', 'China'))"
256
-
257
- # array and string
258
- @d2.where('GDP > ?').select_sql.should ==
259
- "SELECT * FROM test WHERE (region = 'Asia') AND (GDP > ?)"
260
-
261
- # string and string
262
- @d3.where('b = 2').select_sql.should ==
263
- "SELECT * FROM test WHERE (a = 1) AND (b = 2)"
264
-
265
- # string and hash
266
- @d3.where(:c => 3).select_sql.should ==
267
- "SELECT * FROM test WHERE (a = 1) AND (c = 3)"
268
-
269
- # string and array
270
- @d3.where('(d = ?)', 4).select_sql.should ==
271
- "SELECT * FROM test WHERE (a = 1) AND (d = 4)"
272
-
273
- # string and proc expr
274
- @d3.where {:e < 5}.select_sql.should ==
275
- "SELECT * FROM test WHERE (a = 1) AND (e < 5)"
276
- end
277
-
278
- specify "should raise if the dataset is grouped" do
279
- proc {@dataset.group(:t).where(:a => 1)}.should raise_error
280
- end
281
-
282
- specify "should accept ranges" do
283
- @dataset.filter(:id => 4..7).sql.should ==
284
- 'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
285
- @dataset.filter(:id => 4...7).sql.should ==
286
- 'SELECT * FROM test WHERE (id >= 4 AND id < 7)'
287
-
288
- @dataset.filter {:id == (4..7)}.sql.should ==
289
- 'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
290
-
291
- @dataset.filter {:id.in?(4..7)}.sql.should ==
292
- 'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
293
-
294
- @dataset.filter(:table__id => 4..7).sql.should ==
295
- 'SELECT * FROM test WHERE (table.id >= 4 AND table.id <= 7)'
296
- @dataset.filter(:table__id => 4...7).sql.should ==
297
- 'SELECT * FROM test WHERE (table.id >= 4 AND table.id < 7)'
298
-
299
- @dataset.filter {:table__id == (4..7)}.sql.should ==
300
- 'SELECT * FROM test WHERE (table.id >= 4 AND table.id <= 7)'
301
- @dataset.filter {:table__id.in?(4..7)}.sql.should ==
302
- 'SELECT * FROM test WHERE (table.id >= 4 AND table.id <= 7)'
303
- end
304
-
305
- specify "should accept nil" do
306
- @dataset.filter(:owner_id => nil).sql.should ==
307
- 'SELECT * FROM test WHERE (owner_id IS NULL)'
308
-
309
- @dataset.filter{:owner_id.nil?}.sql.should ==
310
- 'SELECT * FROM test WHERE (owner_id IS NULL)'
311
- end
312
-
313
- specify "should accept a subquery" do
314
- # select all countries that have GDP greater than the average for Asia
315
- @dataset.filter('gdp > ?', @d1.select(:gdp.AVG)).sql.should ==
316
- "SELECT * FROM test WHERE gdp > (SELECT avg(gdp) FROM test WHERE (region = 'Asia'))"
317
-
318
- @dataset.filter(:id => @d1.select(:id)).sql.should ==
319
- "SELECT * FROM test WHERE (id IN (SELECT id FROM test WHERE (region = 'Asia')))"
320
- end
321
-
322
- specify "should accept a subquery for an EXISTS clause" do
323
- a = @dataset.filter {:price < 100}
324
- @dataset.filter(a.exists).sql.should ==
325
- 'SELECT * FROM test WHERE EXISTS (SELECT 1 FROM test WHERE (price < 100))'
326
- end
327
-
328
- specify "should accept proc expressions" do
329
- d = @d1.select(:gdp.AVG)
330
- @dataset.filter {:gdp > d}.sql.should ==
331
- "SELECT * FROM test WHERE (gdp > (SELECT avg(gdp) FROM test WHERE (region = 'Asia')))"
332
-
333
- @dataset.filter {:id.in(4..7)}.sql.should ==
334
- 'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
335
-
336
- @dataset.filter {:c == 3}.sql.should ==
337
- 'SELECT * FROM test WHERE (c = 3)'
338
-
339
- @dataset.filter {:id == :items__id}.sql.should ==
340
- 'SELECT * FROM test WHERE (id = items.id)'
341
-
342
- @dataset.filter {:a < 1}.sql.should ==
343
- 'SELECT * FROM test WHERE (a < 1)'
344
-
345
- @dataset.filter {:a != 1}.sql.should ==
346
- 'SELECT * FROM test WHERE (NOT (a = 1))'
347
-
348
- @dataset.filter {:a >= 1 && :b <= 2}.sql.should ==
349
- 'SELECT * FROM test WHERE ((a >= 1) AND (b <= 2))'
350
-
351
- @dataset.filter {:c.like 'ABC%'}.sql.should ==
352
- "SELECT * FROM test WHERE (c LIKE 'ABC%')"
353
-
354
- @dataset.filter {:c.like? 'ABC%'}.sql.should ==
355
- "SELECT * FROM test WHERE (c LIKE 'ABC%')"
356
- end
357
-
358
- specify "should raise if receiving a single boolean value" do
359
- # the result of erroneous use of comparison not in a block
360
- # so instead of filter{:x == y} someone writes filter(:x == y)
361
-
362
- proc {@dataset.filter(:a == 1)}.should raise_error(Sequel::Error::InvalidFilter)
363
- proc {@dataset.filter(:a != 1)}.should raise_error(Sequel::Error::InvalidFilter)
364
- end
365
- end
366
-
367
- context "Dataset#or" do
368
- setup do
369
- @dataset = Sequel::Dataset.new(nil).from(:test)
370
- @d1 = @dataset.where(:x => 1)
371
- end
372
-
373
- specify "should raise if no filter exists" do
374
- proc {@dataset.or(:a => 1)}.should raise_error(Sequel::Error)
375
- end
376
-
377
- specify "should add an alternative expression to the where clause" do
378
- @d1.or(:y => 2).sql.should ==
379
- 'SELECT * FROM test WHERE (x = 1) OR (y = 2)'
380
- end
381
-
382
- specify "should accept all forms of filters" do
383
- # probably not exhaustive, but good enough
384
- @d1.or('(y > ?)', 2).sql.should ==
385
- 'SELECT * FROM test WHERE (x = 1) OR (y > 2)'
386
-
387
- (@d1.or {:yy > 3}).sql.should ==
388
- 'SELECT * FROM test WHERE (x = 1) OR (yy > 3)'
389
- end
390
-
391
- specify "should correctly add parens to give predictable results" do
392
- @d1.filter(:y => 2).or(:z => 3).sql.should ==
393
- 'SELECT * FROM test WHERE ((x = 1) AND (y = 2)) OR (z = 3)'
394
-
395
- @d1.or(:y => 2).filter(:z => 3).sql.should ==
396
- 'SELECT * FROM test WHERE ((x = 1) OR (y = 2)) AND (z = 3)'
397
- end
398
- end
399
-
400
- context "Dataset#and" do
401
- setup do
402
- @dataset = Sequel::Dataset.new(nil).from(:test)
403
- @d1 = @dataset.where(:x => 1)
404
- end
405
-
406
- specify "should raise if no filter exists" do
407
- proc {@dataset.and(:a => 1)}.should raise_error(Sequel::Error)
408
- end
409
-
410
- specify "should add an alternative expression to the where clause" do
411
- @d1.and(:y => 2).sql.should ==
412
- 'SELECT * FROM test WHERE (x = 1) AND (y = 2)'
413
- end
414
-
415
- specify "should accept all forms of filters" do
416
- # probably not exhaustive, but good enough
417
- @d1.and('(y > ?)', 2).sql.should ==
418
- 'SELECT * FROM test WHERE (x = 1) AND (y > 2)'
419
-
420
- (@d1.and {:yy > 3}).sql.should ==
421
- 'SELECT * FROM test WHERE (x = 1) AND (yy > 3)'
422
- end
423
-
424
- specify "should correctly add parens to give predictable results" do
425
- @d1.or(:y => 2).and(:z => 3).sql.should ==
426
- 'SELECT * FROM test WHERE ((x = 1) OR (y = 2)) AND (z = 3)'
427
-
428
- @d1.and(:y => 2).or(:z => 3).sql.should ==
429
- 'SELECT * FROM test WHERE ((x = 1) AND (y = 2)) OR (z = 3)'
430
- end
431
- end
432
-
433
- context "Dataset#exclude" do
434
- setup do
435
- @dataset = Sequel::Dataset.new(nil).from(:test)
436
- end
437
-
438
- specify "should correctly include the NOT operator when one condition is given" do
439
- @dataset.exclude(:region=>'Asia').select_sql.should ==
440
- "SELECT * FROM test WHERE (NOT (region = 'Asia'))"
441
- end
442
-
443
- specify "should take multiple conditions as a hash and express the logic correctly in SQL" do
444
- @dataset.exclude(:region => 'Asia', :name => 'Japan').select_sql.
445
- should match(Regexp.union(/WHERE \(NOT \(\(region = 'Asia'\) AND \(name = 'Japan'\)\)\)/,
446
- /WHERE \(NOT \(\(name = 'Japan'\) AND \(region = 'Asia'\)\)\)/))
447
- end
448
-
449
- specify "should parenthesize a single string condition correctly" do
450
- @dataset.exclude("region = 'Asia' AND name = 'Japan'").select_sql.should ==
451
- "SELECT * FROM test WHERE (NOT (region = 'Asia' AND name = 'Japan'))"
452
- end
453
-
454
- specify "should parenthesize an array condition correctly" do
455
- @dataset.exclude('region = ? AND name = ?', 'Asia', 'Japan').select_sql.should ==
456
- "SELECT * FROM test WHERE (NOT (region = 'Asia' AND name = 'Japan'))"
457
- end
458
-
459
- specify "should correctly parenthesize when it is used twice" do
460
- @dataset.exclude(:region => 'Asia').exclude(:name => 'Japan').select_sql.should ==
461
- "SELECT * FROM test WHERE (NOT (region = 'Asia')) AND (NOT (name = 'Japan'))"
462
- end
463
-
464
- specify "should support proc expressions" do
465
- @dataset.exclude {:id == (6...12)}.sql.should ==
466
- 'SELECT * FROM test WHERE (NOT ((id >= 6 AND id < 12)))'
467
- end
468
- end
469
-
470
- context "Dataset#having" do
471
- setup do
472
- @dataset = Sequel::Dataset.new(nil).from(:test)
473
- @grouped = @dataset.group(:region).select(:region, :population.SUM, :gdp.AVG)
474
- @d1 = @grouped.having('sum(population) > 10')
475
- @d2 = @grouped.having(:region => 'Asia')
476
- @columns = "region, sum(population), avg(gdp)"
477
- end
478
-
479
- specify "should raise if the dataset is not grouped" do
480
- proc {@dataset.having('avg(gdp) > 10')}.should raise_error
481
- end
482
-
483
- specify "should affect select statements" do
484
- @d1.select_sql.should ==
485
- "SELECT #{@columns} FROM test GROUP BY region HAVING sum(population) > 10"
486
- end
487
-
488
- specify "should support proc expressions" do
489
- @grouped.having {:sum[:population] > 10}.sql.should ==
490
- "SELECT #{@columns} FROM test GROUP BY region HAVING (sum(population) > 10)"
491
- end
492
- end
493
-
494
- context "a grouped dataset" do
495
- setup do
496
- @dataset = Sequel::Dataset.new(nil).from(:test).group(:type_id)
497
- end
498
-
499
- specify "should raise when trying to generate an update statement" do
500
- proc {@dataset.update_sql(:id => 0)}.should raise_error
501
- end
502
-
503
- specify "should raise when trying to generate a delete statement" do
504
- proc {@dataset.delete_sql}.should raise_error
505
- end
506
-
507
- specify "should specify the grouping in generated select statement" do
508
- @dataset.select_sql.should ==
509
- "SELECT * FROM test GROUP BY type_id"
510
- end
511
- end
512
-
513
- context "Dataset#group_by" do
514
- setup do
515
- @dataset = Sequel::Dataset.new(nil).from(:test).group_by(:type_id)
516
- end
517
-
518
- specify "should raise when trying to generate an update statement" do
519
- proc {@dataset.update_sql(:id => 0)}.should raise_error
520
- end
521
-
522
- specify "should raise when trying to generate a delete statement" do
523
- proc {@dataset.delete_sql}.should raise_error
524
- end
525
-
526
- specify "should specify the grouping in generated select statement" do
527
- @dataset.select_sql.should ==
528
- "SELECT * FROM test GROUP BY type_id"
529
- end
530
- end
531
-
532
- context "Dataset#literal" do
533
- setup do
534
- @dataset = Sequel::Dataset.new(nil).from(:test)
535
- end
536
-
537
- specify "should escape strings properly" do
538
- @dataset.literal('abc').should == "'abc'"
539
- @dataset.literal('a"x"bc').should == "'a\"x\"bc'"
540
- @dataset.literal("a'bc").should == "'a''bc'"
541
- @dataset.literal("a''bc").should == "'a''''bc'"
542
- end
543
-
544
- specify "should literalize numbers properly" do
545
- @dataset.literal(1).should == "1"
546
- @dataset.literal(1.5).should == "1.5"
547
- end
548
-
549
- specify "should literalize nil as NULL" do
550
- @dataset.literal(nil).should == "NULL"
551
- end
552
-
553
- specify "should literalize an array properly" do
554
- @dataset.literal([]).should == "NULL"
555
- @dataset.literal([1, 'abc', 3]).should == "1, 'abc', 3"
556
- @dataset.literal([1, "a'b''c", 3]).should == "1, 'a''b''''c', 3"
557
- end
558
-
559
- specify "should literalize symbols as column references" do
560
- @dataset.literal(:name).should == "name"
561
- @dataset.literal(:items__name).should == "items.name"
562
- end
563
-
564
- specify "should raise an error for unsupported types" do
565
- proc {@dataset.literal({})}.should raise_error
566
- end
567
-
568
- specify "should literalize datasets as subqueries" do
569
- d = @dataset.from(:test)
570
- d.literal(d).should == "(#{d.sql})"
571
- end
572
-
573
- specify "should literalize Time properly" do
574
- t = Time.now
575
- s = t.strftime("TIMESTAMP '%Y-%m-%d %H:%M:%S'")
576
- @dataset.literal(t).should == s
577
- end
578
-
579
- specify "should literalize Date properly" do
580
- d = Date.today
581
- s = d.strftime("DATE '%Y-%m-%d'")
582
- @dataset.literal(d).should == s
583
- end
584
-
585
- specify "should not literalize expression strings" do
586
- @dataset.literal('col1 + 2'.expr).should == 'col1 + 2'
587
-
588
- @dataset.update_sql(:a => 'a + 2'.expr).should ==
589
- 'UPDATE test SET a = a + 2'
590
- end
591
-
592
- specify "should literalize BigDecimal instances correctly" do
593
- @dataset.literal(BigDecimal.new("80")).should == "80.0"
594
- end
595
- end
596
-
597
- context "Dataset#from" do
598
- setup do
599
- @dataset = Sequel::Dataset.new(nil)
600
- end
601
-
602
- specify "should accept a Dataset" do
603
- proc {@dataset.from(@dataset)}.should_not raise_error
604
- end
605
-
606
- specify "should format a Dataset as a subquery if it has had options set" do
607
- @dataset.from(@dataset.from(:a).where(:a=>1)).select_sql.should ==
608
- "SELECT * FROM (SELECT * FROM a WHERE (a = 1)) t1"
609
- end
610
-
611
- specify "should automatically alias sub-queries" do
612
- @dataset.from(@dataset.from(:a).group(:b)).select_sql.should ==
613
- "SELECT * FROM (SELECT * FROM a GROUP BY b) t1"
614
-
615
- d1 = @dataset.from(:a).group(:b)
616
- d2 = @dataset.from(:c).group(:d)
617
-
618
- @dataset.from(d1, d2).sql.should ==
619
- "SELECT * FROM (SELECT * FROM a GROUP BY b) t1, (SELECT * FROM c GROUP BY d) t2"
620
- end
621
-
622
- specify "should accept a hash for aliasing" do
623
- @dataset.from(:a => :b).sql.should ==
624
- "SELECT * FROM a b"
625
-
626
- @dataset.from(@dataset.from(:a).group(:b) => :c).sql.should ==
627
- "SELECT * FROM (SELECT * FROM a GROUP BY b) c"
628
- end
629
-
630
- specify "should use the relevant table name if given a simple dataset" do
631
- @dataset.from(@dataset.from(:a)).select_sql.should ==
632
- "SELECT * FROM a"
633
- end
634
-
635
- specify "should raise if no source is given" do
636
- proc {@dataset.from(@dataset.from).select_sql}.should raise_error(Sequel::Error)
637
- end
638
- end
639
-
640
- context "Dataset#select" do
641
- setup do
642
- @d = Sequel::Dataset.new(nil).from(:test)
643
- end
644
-
645
- specify "should accept variable arity" do
646
- @d.select(:name).sql.should == 'SELECT name FROM test'
647
- @d.select(:a, :b, :test__c).sql.should == 'SELECT a, b, test.c FROM test'
648
- end
649
-
650
- specify "should accept symbols and literal strings" do
651
- @d.select('aaa'.lit).sql.should == 'SELECT aaa FROM test'
652
- @d.select(:a, 'b'.lit).sql.should == 'SELECT a, b FROM test'
653
- @d.select(:test__cc, 'test.d AS e'.lit).sql.should ==
654
- 'SELECT test.cc, test.d AS e FROM test'
655
- @d.select('test.d AS e'.lit, :test__cc).sql.should ==
656
- 'SELECT test.d AS e, test.cc FROM test'
657
-
658
- # symbol helpers
659
- @d.select(:test.ALL).sql.should ==
660
- 'SELECT test.* FROM test'
661
- @d.select(:test__name.AS(:n)).sql.should ==
662
- 'SELECT test.name AS n FROM test'
663
- @d.select(:test__name___n).sql.should ==
664
- 'SELECT test.name AS n FROM test'
665
- end
666
-
667
- specify "should use the wildcard if no arguments are given" do
668
- @d.select.sql.should == 'SELECT * FROM test'
669
- end
670
-
671
- specify "should accept a hash for AS values" do
672
- @d.select(:name => 'n', :__ggh => 'age').sql.should =~
673
- /SELECT ((name AS n, __ggh AS age)|(__ggh AS age, name AS n)) FROM test/
674
- end
675
-
676
- specify "should overrun the previous select option" do
677
- @d.select(:a, :b, :c).select.sql.should == 'SELECT * FROM test'
678
- @d.select(:price).select(:name).sql.should == 'SELECT name FROM test'
679
- end
680
-
681
- specify "should accept arbitrary objects and literalize them correctly" do
682
- @d.select(1, :a, 't').sql.should == "SELECT 1, a, 't' FROM test"
683
-
684
- @d.select(nil, :sum[:t], :x___y).sql.should == "SELECT NULL, sum(t), x AS y FROM test"
685
-
686
- @d.select(nil, 1, :x => :y).sql.should == "SELECT NULL, 1, x AS y FROM test"
687
- end
688
- end
689
-
690
- context "Dataset#order" do
691
- setup do
692
- @dataset = Sequel::Dataset.new(nil).from(:test)
693
- end
694
-
695
- specify "should include an ORDER BY clause in the select statement" do
696
- @dataset.order(:name).sql.should ==
697
- 'SELECT * FROM test ORDER BY name'
698
- end
699
-
700
- specify "should accept multiple arguments" do
701
- @dataset.order(:name, :price.DESC).sql.should ==
702
- 'SELECT * FROM test ORDER BY name, price DESC'
703
- end
704
-
705
- specify "should overrun a previous ordering" do
706
- @dataset.order(:name).order(:stamp).sql.should ==
707
- 'SELECT * FROM test ORDER BY stamp'
708
- end
709
-
710
- specify "should accept a string" do
711
- @dataset.order('dada ASC'.lit).sql.should ==
712
- 'SELECT * FROM test ORDER BY dada ASC'
713
- end
714
- end
715
-
716
- context "Dataset#order_by" do
717
- setup do
718
- @dataset = Sequel::Dataset.new(nil).from(:test)
719
- end
720
-
721
- specify "should include an ORDER BY clause in the select statement" do
722
- @dataset.order_by(:name).sql.should ==
723
- 'SELECT * FROM test ORDER BY name'
724
- end
725
-
726
- specify "should accept multiple arguments" do
727
- @dataset.order_by(:name, :price.DESC).sql.should ==
728
- 'SELECT * FROM test ORDER BY name, price DESC'
729
- end
730
-
731
- specify "should overrun a previous ordering" do
732
- @dataset.order_by(:name).order(:stamp).sql.should ==
733
- 'SELECT * FROM test ORDER BY stamp'
734
- end
735
-
736
- specify "should accept a string" do
737
- @dataset.order_by('dada ASC'.lit).sql.should ==
738
- 'SELECT * FROM test ORDER BY dada ASC'
739
- end
740
- end
741
-
742
- context "Dataset#reverse_order" do
743
- setup do
744
- @dataset = Sequel::Dataset.new(nil).from(:test)
745
- end
746
-
747
- specify "should use DESC as default order" do
748
- @dataset.reverse_order(:name).sql.should ==
749
- 'SELECT * FROM test ORDER BY name DESC'
750
- end
751
-
752
- specify "should invert the order given" do
753
- @dataset.reverse_order(:name.DESC).sql.should ==
754
- 'SELECT * FROM test ORDER BY name'
755
- end
756
-
757
- specify "should accept multiple arguments" do
758
- @dataset.reverse_order(:name, :price.DESC).sql.should ==
759
- 'SELECT * FROM test ORDER BY name DESC, price'
760
- end
761
-
762
- specify "should reverse a previous ordering if no arguments are given" do
763
- @dataset.order(:name).reverse_order.sql.should ==
764
- 'SELECT * FROM test ORDER BY name DESC'
765
- @dataset.order(:clumsy.DESC, :fool).reverse_order.sql.should ==
766
- 'SELECT * FROM test ORDER BY clumsy, fool DESC'
767
- end
768
- end
769
-
770
- context "Dataset#limit" do
771
- setup do
772
- @dataset = Sequel::Dataset.new(nil).from(:test)
773
- end
774
-
775
- specify "should include a LIMIT clause in the select statement" do
776
- @dataset.limit(10).sql.should ==
777
- 'SELECT * FROM test LIMIT 10'
778
- end
779
-
780
- specify "should accept ranges" do
781
- @dataset.limit(3..7).sql.should ==
782
- 'SELECT * FROM test LIMIT 5 OFFSET 3'
783
-
784
- @dataset.limit(3...7).sql.should ==
785
- 'SELECT * FROM test LIMIT 4 OFFSET 3'
786
- end
787
-
788
- specify "should include an offset if a second argument is given" do
789
- @dataset.limit(6, 10).sql.should ==
790
- 'SELECT * FROM test LIMIT 6 OFFSET 10'
791
- end
792
- end
793
-
794
- context "Dataset#naked" do
795
- setup do
796
- @d1 = Sequel::Dataset.new(nil, {1 => 2, 3 => 4})
797
- @d2 = Sequel::Dataset.new(nil, {1 => 2, 3 => 4}).set_model(Object)
798
- end
799
-
800
- specify "should return a clone with :naked option set" do
801
- naked = @d1.naked
802
- naked.opts[:naked].should be_true
803
- end
804
-
805
- specify "should remove any existing reference to a model class" do
806
- naked = @d2.naked
807
- naked.opts[:models].should be_nil
808
- end
809
- end
810
-
811
- context "Dataset#qualified_column_name" do
812
- setup do
813
- @dataset = Sequel::Dataset.new(nil).from(:test)
814
- end
815
-
816
- specify "should return the same if already qualified" do
817
- @dataset.qualified_column_name('test.a'.lit, :items).should == 'test.a'
818
- @dataset.qualified_column_name(:ccc__b, :items).should == :ccc__b
819
- end
820
-
821
- specify "should qualify the column with the supplied table name" do
822
- @dataset.qualified_column_name('a'.lit, :items).to_s(@dataset).should == 'items.a'
823
- @dataset.qualified_column_name(:b1, :items).to_s(@dataset).should == 'items.b1'
824
- end
825
- end
826
-
827
- class DummyDataset < Sequel::Dataset
828
- VALUES = [
829
- {:a => 1, :b => 2},
830
- {:a => 3, :b => 4},
831
- {:a => 5, :b => 6}
832
- ]
833
- def fetch_rows(sql, &block)
834
- VALUES.each(&block)
835
- end
836
- end
837
-
838
- context "Dataset#map" do
839
- setup do
840
- @d = DummyDataset.new(nil).from(:items)
841
- end
842
-
843
- specify "should provide the usual functionality if no argument is given" do
844
- @d.map {|n| n[:a] + n[:b]}.should == [3, 7, 11]
845
- end
846
-
847
- specify "should map using #[column name] if column name is given" do
848
- @d.map(:a).should == [1, 3, 5]
849
- end
850
-
851
- specify "should return the complete dataset values if nothing is given" do
852
- @d.map.should == DummyDataset::VALUES
853
- end
854
- end
855
-
856
- context "Dataset#to_hash" do
857
- setup do
858
- @d = DummyDataset.new(nil).from(:items)
859
- end
860
-
861
- specify "should provide a hash with the first column as key and the second as value" do
862
- @d.to_hash(:a, :b).should == {1 => 2, 3 => 4, 5 => 6}
863
- @d.to_hash(:b, :a).should == {2 => 1, 4 => 3, 6 => 5}
864
- end
865
- end
866
-
867
- context "Dataset#uniq" do
868
- setup do
869
- @dataset = Sequel::Dataset.new(nil).from(:test).select(:name)
870
- end
871
-
872
- specify "should include DISTINCT clause in statement" do
873
- @dataset.uniq.sql.should == 'SELECT DISTINCT name FROM test'
874
- end
875
-
876
- specify "should be aliased by Dataset#distinct" do
877
- @dataset.distinct.sql.should == 'SELECT DISTINCT name FROM test'
878
- end
879
-
880
- specify "should accept an expression list" do
881
- @dataset.uniq(:a, :b).sql.should == 'SELECT DISTINCT ON (a, b) name FROM test'
882
-
883
- @dataset.uniq(:stamp.cast_as(:integer), :node_id).sql.should == 'SELECT DISTINCT ON (cast(stamp AS integer), node_id) name FROM test'
884
- end
885
- end
886
-
887
- context "Dataset#count" do
888
- setup do
889
- @c = Class.new(Sequel::Dataset) do
890
- def self.sql
891
- @@sql
892
- end
893
-
894
- def fetch_rows(sql)
895
- @@sql = sql
896
- yield({1 => 1})
897
- end
898
- end
899
- @dataset = @c.new(nil).from(:test)
900
- end
901
-
902
- specify "should format SQL properly" do
903
- @dataset.count.should == 1
904
- @c.sql.should == 'SELECT COUNT(*) FROM test'
905
- end
906
-
907
- specify "should be aliased by #size" do
908
- @dataset.size.should == 1
909
- end
910
-
911
- specify "should include the where clause if it's there" do
912
- @dataset.filter {:abc < 30}.count.should == 1
913
- @c.sql.should == 'SELECT COUNT(*) FROM test WHERE (abc < 30)'
914
- end
915
-
916
- specify "should count properly for datasets with fixed sql" do
917
- @dataset.opts[:sql] = "select abc from xyz"
918
- @dataset.count.should == 1
919
- @c.sql.should == "SELECT COUNT(*) FROM (select abc from xyz) AS c"
920
- end
921
- end
922
-
923
-
924
- context "Dataset#group_and_count" do
925
- setup do
926
- @c = Class.new(Sequel::Dataset) do
927
- def self.sql
928
- @@sql
929
- end
930
-
931
- def fetch_rows(sql)
932
- @@sql = sql
933
- yield({1 => 1})
934
- end
935
- end
936
- @ds = @c.new(nil).from(:test)
937
- end
938
-
939
- specify "should format SQL properly" do
940
- @ds.group_and_count(:name).sql.should == "SELECT name, count(name) AS count FROM test GROUP BY name ORDER BY count"
941
- end
942
- end
943
- context "Dataset#empty?" do
944
- specify "should return true if #count == 0" do
945
- @c = Class.new(Sequel::Dataset) do
946
- def count
947
- 0
948
- end
949
- end
950
- @dataset = @c.new(nil).from(:test)
951
- @dataset.empty?.should be_true
952
-
953
- @c = Class.new(Sequel::Dataset) do
954
- def count
955
- 1
956
- end
957
- end
958
- @dataset = @c.new(nil).from(:test)
959
- @dataset.empty?.should be_false
960
- end
961
- end
962
-
963
- context "Dataset#join_table" do
964
- setup do
965
- @d = Sequel::Dataset.new(nil).from(:items)
966
- end
967
-
968
- specify "should format the JOIN clause properly" do
969
- @d.join_table(:left_outer, :categories, :category_id => :id).sql.should ==
970
- 'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.category_id = items.id)'
971
- end
972
-
973
- specify "should include WHERE clause if applicable" do
974
- @d.filter {:price < 100}.join_table(:right_outer, :categories, :category_id => :id).sql.should ==
975
- 'SELECT * FROM items RIGHT OUTER JOIN categories ON (categories.category_id = items.id) WHERE (price < 100)'
976
- end
977
-
978
- specify "should include ORDER BY clause if applicable" do
979
- @d.order(:stamp).join_table(:full_outer, :categories, :category_id => :id).sql.should ==
980
- 'SELECT * FROM items FULL OUTER JOIN categories ON (categories.category_id = items.id) ORDER BY stamp'
981
- end
982
-
983
- specify "should support multiple joins" do
984
- @d.join_table(:inner, :b, :items_id).join_table(:left_outer, :c, :b_id => :b__id).sql.should ==
985
- 'SELECT * FROM items INNER JOIN b ON (b.items_id = items.id) LEFT OUTER JOIN c ON (c.b_id = b.id)'
986
- end
987
-
988
- specify "should use id as implicit relation primary key if omitted" do
989
- @d.join_table(:left_outer, :categories, :category_id).sql.should ==
990
- @d.join_table(:left_outer, :categories, :category_id => :id).sql
991
-
992
- # when doing multiple joins, id should be qualified using the last joined table
993
- @d.join_table(:right_outer, :b, :items_id).join_table(:full_outer, :c, :b_id).sql.should ==
994
- 'SELECT * FROM items RIGHT OUTER JOIN b ON (b.items_id = items.id) FULL OUTER JOIN c ON (c.b_id = b.id)'
995
- end
996
-
997
- specify "should support left outer joins" do
998
- @d.join_table(:left_outer, :categories, :category_id).sql.should ==
999
- 'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.category_id = items.id)'
1000
-
1001
- @d.left_outer_join(:categories, :category_id).sql.should ==
1002
- 'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.category_id = items.id)'
1003
- end
1004
-
1005
- specify "should support right outer joins" do
1006
- @d.join_table(:right_outer, :categories, :category_id).sql.should ==
1007
- 'SELECT * FROM items RIGHT OUTER JOIN categories ON (categories.category_id = items.id)'
1008
-
1009
- @d.right_outer_join(:categories, :category_id).sql.should ==
1010
- 'SELECT * FROM items RIGHT OUTER JOIN categories ON (categories.category_id = items.id)'
1011
- end
1012
-
1013
- specify "should support full outer joins" do
1014
- @d.join_table(:full_outer, :categories, :category_id).sql.should ==
1015
- 'SELECT * FROM items FULL OUTER JOIN categories ON (categories.category_id = items.id)'
1016
-
1017
- @d.full_outer_join(:categories, :category_id).sql.should ==
1018
- 'SELECT * FROM items FULL OUTER JOIN categories ON (categories.category_id = items.id)'
1019
- end
1020
-
1021
- specify "should support inner joins" do
1022
- @d.join_table(:inner, :categories, :category_id).sql.should ==
1023
- 'SELECT * FROM items INNER JOIN categories ON (categories.category_id = items.id)'
1024
-
1025
- @d.inner_join(:categories, :category_id).sql.should ==
1026
- 'SELECT * FROM items INNER JOIN categories ON (categories.category_id = items.id)'
1027
- end
1028
-
1029
- specify "should default to an inner join" do
1030
- @d.join_table(nil, :categories, :category_id).sql.should ==
1031
- 'SELECT * FROM items INNER JOIN categories ON (categories.category_id = items.id)'
1032
-
1033
- @d.join(:categories, :category_id).sql.should ==
1034
- 'SELECT * FROM items INNER JOIN categories ON (categories.category_id = items.id)'
1035
- end
1036
-
1037
- specify "should raise if an invalid join type is specified" do
1038
- proc {@d.join_table(:invalid, :a, :b)}.should raise_error(Sequel::Error)
1039
- end
1040
-
1041
- specify "should treat aliased tables correctly" do
1042
- @d.from('stats s').join('players p', :id => :player_id).sql.should ==
1043
- 'SELECT * FROM stats s INNER JOIN players p ON (p.id = s.player_id)'
1044
- end
1045
-
1046
- specify "should allow for arbitrary conditions in the JOIN clause" do
1047
- @d.join_table(:left_outer, :categories, :status => 0).sql.should ==
1048
- 'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.status = 0)'
1049
- @d.join_table(:left_outer, :categories, :categorizable_type => "Post").sql.should ==
1050
- "SELECT * FROM items LEFT OUTER JOIN categories ON (categories.categorizable_type = 'Post')"
1051
- @d.join_table(:left_outer, :categories, :timestamp => "CURRENT_TIMESTAMP".lit).sql.should ==
1052
- "SELECT * FROM items LEFT OUTER JOIN categories ON (categories.timestamp = CURRENT_TIMESTAMP)"
1053
- @d.join_table(:left_outer, :categories, :status => [1, 2, 3]).sql.should ==
1054
- "SELECT * FROM items LEFT OUTER JOIN categories ON (categories.status IN (1, 2, 3))"
1055
- end
1056
- end
1057
-
1058
- context "Dataset#[]=" do
1059
- setup do
1060
- c = Class.new(Sequel::Dataset) do
1061
- def last_sql
1062
- @@last_sql
1063
- end
1064
-
1065
- def update(*args)
1066
- @@last_sql = update_sql(*args)
1067
- end
1068
- end
1069
-
1070
- @d = c.new(nil).from(:items)
1071
- end
1072
-
1073
- specify "should perform an update on the specified filter" do
1074
- @d[:a => 1] = {:x => 3}
1075
- @d.last_sql.should == 'UPDATE items SET x = 3 WHERE (a = 1)'
1076
- end
1077
- end
1078
-
1079
- context "Dataset#set" do
1080
- setup do
1081
- c = Class.new(Sequel::Dataset) do
1082
- def last_sql
1083
- @@last_sql
1084
- end
1085
-
1086
- def update(*args, &block)
1087
- @@last_sql = update_sql(*args, &block)
1088
- end
1089
- end
1090
-
1091
- @d = c.new(nil).from(:items)
1092
- end
1093
-
1094
- specify "should act as alias to #update" do
1095
- @d.set({:x => 3})
1096
- @d.last_sql.should == 'UPDATE items SET x = 3'
1097
-
1098
- @d.set {:x << :x + 1}
1099
- @d.last_sql.should == 'UPDATE items SET x = (x + 1)'
1100
-
1101
- @d.set {(:x|1) << (:x|2) + 1}
1102
- @d.last_sql.should == 'UPDATE items SET x[1] = (x[2] + 1)'
1103
- end
1104
- end
1105
-
1106
-
1107
- context "Dataset#insert_multiple" do
1108
- setup do
1109
- c = Class.new(Sequel::Dataset) do
1110
- attr_reader :inserts
1111
- def insert(arg)
1112
- @inserts ||= []
1113
- @inserts << arg
1114
- end
1115
- end
1116
-
1117
- @d = c.new(nil)
1118
- end
1119
-
1120
- specify "should insert all items in the supplied array" do
1121
- @d.insert_multiple [:aa, 5, 3, {1 => 2}]
1122
- @d.inserts.should == [:aa, 5, 3, {1 => 2}]
1123
- end
1124
-
1125
- specify "should pass array items through the supplied block if given" do
1126
- a = ["inevitable", "hello", "the ticking clock"]
1127
- @d.insert_multiple(a) {|i| i.gsub('l', 'r')}
1128
- @d.inserts.should == ["inevitabre", "herro", "the ticking crock"]
1129
- end
1130
- end
1131
-
1132
- context "Dataset aggregate methods" do
1133
- setup do
1134
- c = Class.new(Sequel::Dataset) do
1135
- def fetch_rows(sql)
1136
- yield({1 => sql})
1137
- end
1138
- end
1139
- @d = c.new(nil).from(:test)
1140
- end
1141
-
1142
- specify "should include min" do
1143
- @d.min(:a).should == 'SELECT min(a) AS v FROM test'
1144
- end
1145
-
1146
- specify "should include max" do
1147
- @d.max(:b).should == 'SELECT max(b) AS v FROM test'
1148
- end
1149
-
1150
- specify "should include sum" do
1151
- @d.sum(:c).should == 'SELECT sum(c) AS v FROM test'
1152
- end
1153
-
1154
- specify "should include avg" do
1155
- @d.avg(:d).should == 'SELECT avg(d) AS v FROM test'
1156
- end
1157
-
1158
- specify "should accept qualified columns" do
1159
- @d.avg(:test__bc).should == 'SELECT avg(test.bc) AS v FROM test'
1160
- end
1161
- end
1162
-
1163
- context "Dataset#range" do
1164
- setup do
1165
- c = Class.new(Sequel::Dataset) do
1166
- @@sql = nil
1167
-
1168
- def last_sql; @@sql; end
1169
-
1170
- def fetch_rows(sql)
1171
- @@sql = sql
1172
- yield(:v1 => 1, :v2 => 10)
1173
- end
1174
- end
1175
- @d = c.new(nil).from(:test)
1176
- end
1177
-
1178
- specify "should generate a correct SQL statement" do
1179
- @d.range(:stamp)
1180
- @d.last_sql.should == "SELECT min(stamp) AS v1, max(stamp) AS v2 FROM test LIMIT 1"
1181
-
1182
- @d.filter {:price > 100}.range(:stamp)
1183
- @d.last_sql.should == "SELECT min(stamp) AS v1, max(stamp) AS v2 FROM test WHERE (price > 100) LIMIT 1"
1184
- end
1185
-
1186
- specify "should return a range object" do
1187
- @d.range(:tryme).should == (1..10)
1188
- @d.last_sql.should == "SELECT min(tryme) AS v1, max(tryme) AS v2 FROM test LIMIT 1"
1189
- end
1190
- end
1191
-
1192
- context "Dataset#range" do
1193
- setup do
1194
- c = Class.new(Sequel::Dataset) do
1195
- @@sql = nil
1196
-
1197
- def last_sql; @@sql; end
1198
-
1199
- def fetch_rows(sql)
1200
- @@sql = sql
1201
- yield(:v => 1234)
1202
- end
1203
- end
1204
- @d = c.new(nil).from(:test)
1205
- end
1206
-
1207
- specify "should generate a correct SQL statement" do
1208
- @d.interval(:stamp)
1209
- @d.last_sql.should == "SELECT (max(stamp) - min(stamp)) AS v FROM test LIMIT 1"
1210
-
1211
- @d.filter {:price > 100}.interval(:stamp)
1212
- @d.last_sql.should == "SELECT (max(stamp) - min(stamp)) AS v FROM test WHERE (price > 100) LIMIT 1"
1213
- end
1214
-
1215
- specify "should return a range object" do
1216
- @d.interval(:tryme).should == 1234
1217
- @d.last_sql.should == "SELECT (max(tryme) - min(tryme)) AS v FROM test LIMIT 1"
1218
- end
1219
- end
1220
-
1221
- context "Dataset#first" do
1222
- setup do
1223
- @c = Class.new(Sequel::Dataset) do
1224
- @@last_dataset = nil
1225
- @@last_opts = nil
1226
-
1227
- def self.last_dataset
1228
- @@last_dataset
1229
- end
1230
-
1231
- def self.last_opts
1232
- @@last_opts
1233
- end
1234
-
1235
- def single_record(opts = nil)
1236
- @@last_opts = @opts.merge(opts || {})
1237
- {:a => 1, :b => 2}
1238
- end
1239
-
1240
- def all
1241
- @@last_dataset = self
1242
- [{:a => 1, :b => 2}] * @opts[:limit]
1243
- end
1244
- end
1245
- @d = @c.new(nil).from(:test)
1246
- end
1247
-
1248
- specify "should return the first matching record if a hash is specified" do
1249
- @d.first(:z => 26).should == {:a => 1, :b => 2}
1250
- @c.last_opts[:where].should == ('(z = 26)')
1251
-
1252
- @d.first('z = ?', 15)
1253
- @c.last_opts[:where].should == ('z = 15')
1254
- end
1255
-
1256
- specify "should return the first matching record if a block is given" do
1257
- @d.first {:z > 26}.should == {:a => 1, :b => 2}
1258
- @c.last_opts[:where].should == ('(z > 26)')
1259
- end
1260
-
1261
- specify "should return a single record if no argument is given" do
1262
- @d.first.should == {:a => 1, :b => 2}
1263
- end
1264
-
1265
- specify "should set the limit according to the given number" do
1266
- @d.first
1267
- @c.last_opts[:limit].should == 1
1268
-
1269
- i = rand(10) + 10
1270
- @d.first(i)
1271
- @c.last_dataset.opts[:limit].should == i
1272
- end
1273
-
1274
- specify "should return an array with the records if argument is greater than 1" do
1275
- i = rand(10) + 10
1276
- r = @d.first(i)
1277
- r.should be_a_kind_of(Array)
1278
- r.size.should == i
1279
- r.each {|row| row.should == {:a => 1, :b => 2}}
1280
- end
1281
- end
1282
-
1283
- context "Dataset#last" do
1284
- setup do
1285
- @c = Class.new(Sequel::Dataset) do
1286
- @@last_dataset = nil
1287
-
1288
- def self.last_dataset
1289
- @@last_dataset
1290
- end
1291
-
1292
- def single_record(opts = nil)
1293
- @@last_dataset = clone_merge(opts) if opts
1294
- {:a => 1, :b => 2}
1295
- end
1296
-
1297
- def all
1298
- @@last_dataset = self
1299
- [{:a => 1, :b => 2}] * @opts[:limit]
1300
- end
1301
- end
1302
- @d = @c.new(nil).from(:test)
1303
- end
1304
-
1305
- specify "should raise if no order is given" do
1306
- proc {@d.last}.should raise_error(Sequel::Error)
1307
- proc {@d.last(2)}.should raise_error(Sequel::Error)
1308
- proc {@d.order(:a).last}.should_not raise_error
1309
- proc {@d.order(:a).last(2)}.should_not raise_error
1310
- end
1311
-
1312
- specify "should invert the order" do
1313
- @d.order(:a).last
1314
- @d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:a.DESC])
1315
-
1316
- @d.order(:b.DESC).last
1317
- @d.literal(@c.last_dataset.opts[:order]).should == @d.literal(:b)
1318
-
1319
- @d.order(:c, :d).last
1320
- @d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:c.DESC, :d.DESC])
1321
-
1322
- @d.order(:e.DESC, :f).last
1323
- @d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:e, :f.DESC])
1324
- end
1325
-
1326
- specify "should return the first matching record if a hash is specified" do
1327
- @d.order(:a).last(:z => 26).should == {:a => 1, :b => 2}
1328
- @c.last_dataset.opts[:where].should == ('(z = 26)')
1329
-
1330
- @d.order(:a).last('z = ?', 15)
1331
- @c.last_dataset.opts[:where].should == ('z = 15')
1332
- end
1333
-
1334
- specify "should return a single record if no argument is given" do
1335
- @d.order(:a).last.should == {:a => 1, :b => 2}
1336
- end
1337
-
1338
- specify "should set the limit according to the given number" do
1339
- i = rand(10) + 10
1340
- r = @d.order(:a).last(i)
1341
- @c.last_dataset.opts[:limit].should == i
1342
- end
1343
-
1344
- specify "should return an array with the records if argument is greater than 1" do
1345
- i = rand(10) + 10
1346
- r = @d.order(:a).last(i)
1347
- r.should be_a_kind_of(Array)
1348
- r.size.should == i
1349
- r.each {|row| row.should == {:a => 1, :b => 2}}
1350
- end
1351
- end
1352
-
1353
- context "Dataset set operations" do
1354
- setup do
1355
- @a = Sequel::Dataset.new(nil).from(:a).filter(:z => 1)
1356
- @b = Sequel::Dataset.new(nil).from(:b).filter(:z => 2)
1357
- end
1358
-
1359
- specify "should support UNION and UNION ALL" do
1360
- @a.union(@b).sql.should == \
1361
- "SELECT * FROM a WHERE (z = 1) UNION SELECT * FROM b WHERE (z = 2)"
1362
- @b.union(@a, true).sql.should == \
1363
- "SELECT * FROM b WHERE (z = 2) UNION ALL SELECT * FROM a WHERE (z = 1)"
1364
- end
1365
-
1366
- specify "should support INTERSECT and INTERSECT ALL" do
1367
- @a.intersect(@b).sql.should == \
1368
- "SELECT * FROM a WHERE (z = 1) INTERSECT SELECT * FROM b WHERE (z = 2)"
1369
- @b.intersect(@a, true).sql.should == \
1370
- "SELECT * FROM b WHERE (z = 2) INTERSECT ALL SELECT * FROM a WHERE (z = 1)"
1371
- end
1372
-
1373
- specify "should support EXCEPT and EXCEPT ALL" do
1374
- @a.except(@b).sql.should == \
1375
- "SELECT * FROM a WHERE (z = 1) EXCEPT SELECT * FROM b WHERE (z = 2)"
1376
- @b.except(@a, true).sql.should == \
1377
- "SELECT * FROM b WHERE (z = 2) EXCEPT ALL SELECT * FROM a WHERE (z = 1)"
1378
- end
1379
- end
1380
-
1381
- context "Dataset#[]" do
1382
- setup do
1383
- @c = Class.new(Sequel::Dataset) do
1384
- @@last_dataset = nil
1385
-
1386
- def self.last_dataset
1387
- @@last_dataset
1388
- end
1389
-
1390
- def single_record(opts = nil)
1391
- @@last_dataset = opts ? clone_merge(opts) : self
1392
- {1 => 2, 3 => 4}
1393
- end
1394
- end
1395
- @d = @c.new(nil).from(:test)
1396
- end
1397
-
1398
- specify "should return a single record filtered according to the given conditions" do
1399
- @d[:name => 'didi'].should == {1 => 2, 3 => 4}
1400
- @c.last_dataset.opts[:where].should == "(name = 'didi')"
1401
-
1402
- @d[:id => 5..45].should == {1 => 2, 3 => 4}
1403
- @c.last_dataset.opts[:where].should == "(id >= 5 AND id <= 45)"
1404
- end
1405
- end
1406
-
1407
- context "Dataset#single_record" do
1408
- setup do
1409
- @c = Class.new(Sequel::Dataset) do
1410
- def fetch_rows(sql)
1411
- yield sql
1412
- end
1413
- end
1414
- @cc = Class.new(@c) do
1415
- def fetch_rows(sql); end
1416
- end
1417
-
1418
- @d = @c.new(nil).from(:test)
1419
- @e = @cc.new(nil).from(:test)
1420
- end
1421
-
1422
- specify "should call each and return the first record" do
1423
- @d.single_record.should == 'SELECT * FROM test'
1424
- end
1425
-
1426
- specify "should pass opts to each" do
1427
- @d.single_record(:limit => 3).should == 'SELECT * FROM test LIMIT 3'
1428
- end
1429
-
1430
- specify "should return nil if no record is present" do
1431
- @e.single_record.should be_nil
1432
- end
1433
- end
1434
-
1435
- context "Dataset#single_value" do
1436
- setup do
1437
- @c = Class.new(Sequel::Dataset) do
1438
- def fetch_rows(sql)
1439
- yield({1 => sql})
1440
- end
1441
- end
1442
- @cc = Class.new(@c) do
1443
- def fetch_rows(sql); end
1444
- end
1445
-
1446
- @d = @c.new(nil).from(:test)
1447
- @e = @cc.new(nil).from(:test)
1448
- end
1449
-
1450
- specify "should call each and return the first value of the first record" do
1451
- @d.single_value.should == 'SELECT * FROM test'
1452
- end
1453
-
1454
- specify "should pass opts to each" do
1455
- @d.single_value(:limit => 3).should == 'SELECT * FROM test LIMIT 3'
1456
- end
1457
-
1458
- specify "should return nil" do
1459
- @e.single_value.should be_nil
1460
- end
1461
-
1462
- end
1463
-
1464
- context "Dataset#set_row_proc" do
1465
- setup do
1466
- @c = Class.new(Sequel::Dataset) do
1467
- def fetch_rows(sql, &block)
1468
- # yield a hash with kind as the 1 bit of a number
1469
- (1..10).each {|i| block.call({:kind => i[0]})}
1470
- end
1471
- end
1472
- @dataset = @c.new(nil).from(:items)
1473
- end
1474
-
1475
- specify "should cause dataset to pass all rows through the filter" do
1476
- @dataset.set_row_proc {|h| h[:der] = h[:kind] + 2; h}
1477
-
1478
- rows = @dataset.all
1479
- rows.size.should == 10
1480
-
1481
- rows.each {|r| r[:der].should == (r[:kind] + 2)}
1482
- end
1483
-
1484
- specify "should be copied over when dataset is cloned" do
1485
- @dataset.set_row_proc {|h| h[:der] = h[:kind] + 2; h}
1486
-
1487
- @dataset.filter(:a => 1).first.should == {:kind => 1, :der => 3}
1488
- end
1489
- end
1490
-
1491
- context "Dataset#set_model" do
1492
- setup do
1493
- @c = Class.new(Sequel::Dataset) do
1494
- def fetch_rows(sql, &block)
1495
- # yield a hash with kind as the 1 bit of a number
1496
- (1..10).each {|i| block.call({:kind => i[0]})}
1497
- end
1498
- end
1499
- @dataset = @c.new(nil).from(:items)
1500
- @m = Class.new do
1501
- attr_accessor :c, :args
1502
- def initialize(c, *args); @c = c; @args = args; end
1503
- def ==(o); (@c == o.c) && (@args = o.args); end
1504
- end
1505
- end
1506
-
1507
- specify "should clear the models hash and restore the stock #each if nil is specified" do
1508
- @dataset.set_model(@m)
1509
- @dataset.set_model(nil)
1510
- @dataset.first.should == {:kind => 1}
1511
- @dataset.model_classes.should be_nil
1512
- end
1513
-
1514
- specify "should clear the models hash and restore the stock #each if nothing is specified" do
1515
- @dataset.set_model(@m)
1516
- @dataset.set_model(nil)
1517
- @dataset.first.should == {:kind => 1}
1518
- @dataset.model_classes.should be_nil
1519
- end
1520
-
1521
- specify "should alter #each to provide model instances" do
1522
- @dataset.first.should == {:kind => 1}
1523
- @dataset.set_model(@m)
1524
- @dataset.first.should == @m.new({:kind => 1})
1525
- end
1526
-
1527
- specify "should extend the dataset with a #destroy method" do
1528
- @dataset.should_not respond_to(:destroy)
1529
- @dataset.set_model(@m)
1530
- @dataset.should respond_to(:destroy)
1531
- end
1532
-
1533
- specify "should set opts[:naked] to nil" do
1534
- @dataset.opts[:naked] = true
1535
- @dataset.set_model(@m)
1536
- @dataset.opts[:naked].should be_nil
1537
- end
1538
-
1539
- specify "should send additional arguments to the models' initialize method" do
1540
- @dataset.set_model(@m, 7, 6, 5)
1541
- @dataset.first.should == @m.new({:kind => 1}, 7, 6, 5)
1542
- end
1543
-
1544
- specify "should provide support for polymorphic model instantiation" do
1545
- @m1 = Class.new(@m)
1546
- @m2 = Class.new(@m)
1547
- @dataset.set_model(:kind, 0 => @m1, 1 => @m2)
1548
- @dataset.opts[:polymorphic_key].should == :kind
1549
- all = @dataset.all
1550
- all[0].class.should == @m2
1551
- all[1].class.should == @m1
1552
- all[2].class.should == @m2
1553
- all[3].class.should == @m1
1554
- #...
1555
-
1556
- # denude model
1557
- @dataset.set_model(nil)
1558
- @dataset.first.should == {:kind => 1}
1559
- end
1560
-
1561
- specify "should send additional arguments for polymorphic models as well" do
1562
- @m1 = Class.new(@m)
1563
- @m2 = Class.new(@m)
1564
- @dataset.set_model(:kind, {0 => @m1, 1 => @m2}, :hey => :wow)
1565
- all = @dataset.all
1566
- all[0].class.should == @m2; all[0].args.should == [{:hey => :wow}]
1567
- all[1].class.should == @m1; all[1].args.should == [{:hey => :wow}]
1568
- all[2].class.should == @m2; all[2].args.should == [{:hey => :wow}]
1569
- all[3].class.should == @m1; all[3].args.should == [{:hey => :wow}]
1570
- end
1571
-
1572
- specify "should raise for invalid parameters" do
1573
- proc {@dataset.set_model('kind')}.should raise_error(ArgumentError)
1574
- proc {@dataset.set_model(0)}.should raise_error(ArgumentError)
1575
- proc {@dataset.set_model(:kind)}.should raise_error(ArgumentError) # no hash given
1576
- end
1577
- end
1578
-
1579
- context "Dataset#model_classes" do
1580
- setup do
1581
- @c = Class.new(Sequel::Dataset) do
1582
- # # We don't need that for now
1583
- # def fetch_rows(sql, &block)
1584
- # (1..10).each(&block)
1585
- # end
1586
- end
1587
- @dataset = @c.new(nil).from(:items)
1588
- @m = Class.new do
1589
- attr_accessor :c
1590
- def initialize(c); @c = c; end
1591
- def ==(o); @c == o.c; end
1592
- end
1593
- end
1594
-
1595
- specify "should return nil for a naked dataset" do
1596
- @dataset.model_classes.should == nil
1597
- end
1598
-
1599
- specify "should return a {nil => model_class} hash for a model dataset" do
1600
- @dataset.set_model(@m)
1601
- @dataset.model_classes.should == {nil => @m}
1602
- end
1603
-
1604
- specify "should return the polymorphic hash for a polymorphic model dataset" do
1605
- @m1 = Class.new(@m)
1606
- @m2 = Class.new(@m)
1607
- @dataset.set_model(:key, 0 => @m1, 1 => @m2)
1608
- @dataset.model_classes.should == {0 => @m1, 1 => @m2}
1609
- end
1610
- end
1611
-
1612
- context "Dataset#polymorphic_key" do
1613
- setup do
1614
- @c = Class.new(Sequel::Dataset) do
1615
- # # We don't need this for now
1616
- # def fetch_rows(sql, &block)
1617
- # (1..10).each(&block)
1618
- # end
1619
- end
1620
- @dataset = @c.new(nil).from(:items)
1621
- @m = Class.new do
1622
- attr_accessor :c
1623
- def initialize(c); @c = c; end
1624
- def ==(o); @c == o.c; end
1625
- end
1626
- end
1627
-
1628
- specify "should return nil for a naked dataset" do
1629
- @dataset.polymorphic_key.should be_nil
1630
- end
1631
-
1632
- specify "should return the polymorphic key" do
1633
- @dataset.set_model(:id, nil => @m)
1634
- @dataset.polymorphic_key.should == :id
1635
- end
1636
- end
1637
-
1638
- context "A model dataset" do
1639
- setup do
1640
- @c = Class.new(Sequel::Dataset) do
1641
- def fetch_rows(sql, &block)
1642
- (1..10).each(&block)
1643
- end
1644
- end
1645
- @dataset = @c.new(nil).from(:items)
1646
- @m = Class.new do
1647
- attr_accessor :c
1648
- def initialize(c); @c = c; end
1649
- def ==(o); @c == o.c; end
1650
- end
1651
- @dataset.set_model(@m)
1652
- end
1653
-
1654
- specify "should supply naked records if the naked option is specified" do
1655
- @dataset.each {|r| r.class.should == @m}
1656
- @dataset.each(:naked => true) {|r| r.class.should == Fixnum}
1657
- end
1658
- end
1659
-
1660
- context "A polymorphic model dataset" do
1661
- setup do
1662
- @c = Class.new(Sequel::Dataset) do
1663
- def fetch_rows(sql, &block)
1664
- (1..10).each {|i| block.call(:bit => i[0])}
1665
- end
1666
- end
1667
- @dataset = @c.new(nil).from(:items)
1668
- @m = Class.new do
1669
- attr_accessor :c
1670
- def initialize(c); @c = c; end
1671
- def ==(o); @c == o.c; end
1672
- end
1673
- end
1674
-
1675
- specify "should use a nil key in the polymorphic hash to specify the default model class" do
1676
- @m2 = Class.new(@m)
1677
- @dataset.set_model(:bit, nil => @m, 1 => @m2)
1678
- all = @dataset.all
1679
- all[0].class.should == @m2
1680
- all[1].class.should == @m
1681
- all[2].class.should == @m2
1682
- all[3].class.should == @m
1683
- #...
1684
- end
1685
-
1686
- specify "should raise Sequel::Error if no suitable class is found in the polymorphic hash" do
1687
- @m2 = Class.new(@m)
1688
- @dataset.set_model(:bit, 1 => @m2)
1689
- proc {@dataset.all}.should raise_error(Sequel::Error)
1690
- end
1691
-
1692
- specify "should supply naked records if the naked option is specified" do
1693
- @dataset.set_model(:bit, nil => @m)
1694
- @dataset.each(:naked => true) {|r| r.class.should == Hash}
1695
- end
1696
- end
1697
-
1698
- context "Dataset#destroy" do
1699
- setup do
1700
- db = Object.new
1701
- m = Module.new do
1702
- def transaction; yield; end
1703
- end
1704
- db.extend(m)
1705
-
1706
- DESTROYED = []
1707
-
1708
- @m = Class.new do
1709
- def initialize(c)
1710
- @c = c
1711
- end
1712
-
1713
- attr_accessor :c
1714
-
1715
- def ==(o)
1716
- @c == o.c
1717
- end
1718
-
1719
- def destroy
1720
- DESTROYED << self
1721
- end
1722
- end
1723
- MODELS = [@m.new(12), @m.new(13)]
1724
-
1725
- c = Class.new(Sequel::Dataset) do
1726
- def fetch_rows(sql, &block)
1727
- (12..13).each(&block)
1728
- end
1729
- end
1730
-
1731
- @d = c.new(db).from(:test)
1732
- @d.set_model(@m)
1733
- end
1734
-
1735
- specify "should call destroy for every model instance in the dataset" do
1736
- count = @d.destroy
1737
- count.should == 2
1738
- DESTROYED.should == MODELS
1739
- end
1740
-
1741
- specify "should raise error if no models are associated with the dataset" do
1742
- proc {@d.naked.destroy}.should raise_error(Sequel::Error)
1743
- end
1744
- end
1745
-
1746
- context "Dataset#<<" do
1747
- setup do
1748
- @d = Sequel::Dataset.new(nil)
1749
- @d.meta_def(:insert) do
1750
- 1234567890
1751
- end
1752
- end
1753
-
1754
- specify "should call #insert" do
1755
- (@d << {:name => 1}).should == 1234567890
1756
- end
1757
- end
1758
-
1759
- context "A paginated dataset" do
1760
- setup do
1761
- @d = Sequel::Dataset.new(nil)
1762
- @d.meta_def(:count) {153}
1763
-
1764
- @paginated = @d.paginate(1, 20)
1765
- end
1766
-
1767
- specify "should set the limit and offset options correctly" do
1768
- @paginated.opts[:limit].should == 20
1769
- @paginated.opts[:offset].should == 0
1770
- end
1771
-
1772
- specify "should set the page count correctly" do
1773
- @paginated.page_count.should == 8
1774
- @d.paginate(1, 50).page_count.should == 4
1775
- end
1776
-
1777
- specify "should set the current page number correctly" do
1778
- @paginated.current_page.should == 1
1779
- @d.paginate(3, 50).current_page.should == 3
1780
- end
1781
-
1782
- specify "should return the next page number or nil if we're on the last" do
1783
- @paginated.next_page.should == 2
1784
- @d.paginate(4, 50).next_page.should be_nil
1785
- end
1786
-
1787
- specify "should return the previous page number or nil if we're on the last" do
1788
- @paginated.prev_page.should be_nil
1789
- @d.paginate(4, 50).prev_page.should == 3
1790
- end
1791
-
1792
- specify "should return the page range" do
1793
- @paginated.page_range.should == (1..8)
1794
- @d.paginate(4, 50).page_range.should == (1..4)
1795
- end
1796
-
1797
- specify "should return the record range for the current page" do
1798
- @paginated.current_page_record_range.should == (1..20)
1799
- @d.paginate(4, 50).current_page_record_range.should == (151..153)
1800
- @d.paginate(5, 50).current_page_record_range.should == (0..0)
1801
- end
1802
-
1803
- specify "should return the record count for the current page" do
1804
- @paginated.current_page_record_count.should == 20
1805
- @d.paginate(3, 50).current_page_record_count.should == 50
1806
- @d.paginate(4, 50).current_page_record_count.should == 3
1807
- @d.paginate(5, 50).current_page_record_count.should == 0
1808
- end
1809
- end
1810
-
1811
- context "Dataset#columns" do
1812
- setup do
1813
- @dataset = DummyDataset.new(nil).from(:items)
1814
- @dataset.meta_def(:columns=) {|c| @columns = c}
1815
- @dataset.meta_def(:first) {@columns = select_sql(nil)}
1816
- end
1817
-
1818
- specify "should return the value of @columns" do
1819
- @dataset.columns = [:a, :b, :c]
1820
- @dataset.columns.should == [:a, :b, :c]
1821
- end
1822
-
1823
- specify "should call first if @columns is nil" do
1824
- @dataset.columns = nil
1825
- @dataset.columns.should == 'SELECT * FROM items'
1826
- @dataset.opts[:from] = [:nana]
1827
- @dataset.columns.should == 'SELECT * FROM items'
1828
- end
1829
- end
1830
-
1831
- require 'stringio'
1832
-
1833
- context "Dataset#print" do
1834
- setup do
1835
- @output = StringIO.new
1836
- @orig_stdout = $stdout
1837
- $stdout = @output
1838
- @dataset = DummyDataset.new(nil).from(:items)
1839
- end
1840
-
1841
- teardown do
1842
- $stdout = @orig_stdout
1843
- end
1844
-
1845
- specify "should print out a table with the values" do
1846
- @dataset.print(:a, :b)
1847
- @output.rewind
1848
- @output.read.should == \
1849
- "+-+-+\n|a|b|\n+-+-+\n|1|2|\n|3|4|\n|5|6|\n+-+-+\n"
1850
- end
1851
-
1852
- specify "should default to the dataset's columns" do
1853
- @dataset.meta_def(:columns) {[:a, :b]}
1854
- @dataset.print
1855
- @output.rewind
1856
- @output.read.should == \
1857
- "+-+-+\n|a|b|\n+-+-+\n|1|2|\n|3|4|\n|5|6|\n+-+-+\n"
1858
- end
1859
- end
1860
-
1861
- context "Dataset#multi_insert" do
1862
- setup do
1863
- @dbc = Class.new do
1864
- attr_reader :sqls
1865
-
1866
- def execute(sql)
1867
- @sqls ||= []
1868
- @sqls << sql
1869
- end
1870
-
1871
- def transaction
1872
- @sqls ||= []
1873
- @sqls << 'BEGIN'
1874
- yield
1875
- @sqls << 'COMMIT'
1876
- end
1877
- end
1878
- @db = @dbc.new
1879
-
1880
- @ds = Sequel::Dataset.new(@db).from(:items)
1881
-
1882
- @list = [{:name => 'abc'}, {:name => 'def'}, {:name => 'ghi'}]
1883
- end
1884
-
1885
- specify "should join all inserts into a single SQL string" do
1886
- @ds.multi_insert(@list)
1887
- @db.sqls.should == [
1888
- 'BEGIN',
1889
- "INSERT INTO items (name) VALUES ('abc')",
1890
- "INSERT INTO items (name) VALUES ('def')",
1891
- "INSERT INTO items (name) VALUES ('ghi')",
1892
- 'COMMIT'
1893
- ]
1894
- end
1895
-
1896
- specify "should accept the commit_every option for committing every x records" do
1897
- @ds.multi_insert(@list, :commit_every => 2)
1898
- @db.sqls.should == [
1899
- 'BEGIN',
1900
- "INSERT INTO items (name) VALUES ('abc')",
1901
- "INSERT INTO items (name) VALUES ('def')",
1902
- 'COMMIT',
1903
- 'BEGIN',
1904
- "INSERT INTO items (name) VALUES ('ghi')",
1905
- 'COMMIT'
1906
- ]
1907
- end
1908
- end
1909
-
1910
- context "Dataset#query" do
1911
- setup do
1912
- @d = Sequel::Dataset.new(nil)
1913
- end
1914
-
1915
- specify "should support #from" do
1916
- q = @d.query {from :xxx}
1917
- q.class.should == @d.class
1918
- q.sql.should == "SELECT * FROM xxx"
1919
- end
1920
-
1921
- specify "should support #select" do
1922
- q = @d.query do
1923
- select :a, :b___mongo
1924
- from :yyy
1925
- end
1926
- q.class.should == @d.class
1927
- q.sql.should == "SELECT a, b AS mongo FROM yyy"
1928
- end
1929
-
1930
- specify "should support #where" do
1931
- q = @d.query do
1932
- from :zzz
1933
- where {:x + 2 > :y + 3}
1934
- end
1935
- q.class.should == @d.class
1936
- q.sql.should == "SELECT * FROM zzz WHERE ((x + 2) > (y + 3))"
1937
-
1938
- q = @d.from(:zzz).query do
1939
- where {:x > 1 && :y > 2}
1940
- end
1941
- q.class.should == @d.class
1942
- q.sql.should == "SELECT * FROM zzz WHERE ((x > 1) AND (y > 2))"
1943
-
1944
- q = @d.from(:zzz).query do
1945
- where :x => 33
1946
- end
1947
- q.class.should == @d.class
1948
- q.sql.should == "SELECT * FROM zzz WHERE (x = 33)"
1949
- end
1950
-
1951
- specify "should support #group_by and #having" do
1952
- q = @d.query do
1953
- from :abc
1954
- group_by :id
1955
- having {:x >= 2}
1956
- end
1957
- q.class.should == @d.class
1958
- q.sql.should == "SELECT * FROM abc GROUP BY id HAVING (x >= 2)"
1959
- end
1960
-
1961
- specify "should support #order, #order_by" do
1962
- q = @d.query do
1963
- from :xyz
1964
- order_by :stamp
1965
- end
1966
- q.class.should == @d.class
1967
- q.sql.should == "SELECT * FROM xyz ORDER BY stamp"
1968
- end
1969
-
1970
- specify "should raise on non-chainable method calls" do
1971
- proc {@d.query {count}}.should raise_error(Sequel::Error)
1972
- end
1973
-
1974
- specify "should raise on each, insert, update, delete" do
1975
- proc {@d.query {each}}.should raise_error(Sequel::Error)
1976
- proc {@d.query {insert(:x => 1)}}.should raise_error(Sequel::Error)
1977
- proc {@d.query {update(:x => 1)}}.should raise_error(Sequel::Error)
1978
- proc {@d.query {delete}}.should raise_error(Sequel::Error)
1979
- end
1980
- end
1981
-
1982
- context "Dataset" do
1983
- setup do
1984
- @d = Sequel::Dataset.new(nil).from(:x)
1985
- end
1986
-
1987
- specify "should support self-changing select!" do
1988
- @d.select!(:y)
1989
- @d.sql.should == "SELECT y FROM x"
1990
- end
1991
-
1992
- specify "should support self-changing from!" do
1993
- @d.from!(:y)
1994
- @d.sql.should == "SELECT * FROM y"
1995
- end
1996
-
1997
- specify "should support self-changing order!" do
1998
- @d.order!(:y)
1999
- @d.sql.should == "SELECT * FROM x ORDER BY y"
2000
- end
2001
-
2002
- specify "should support self-changing filter!" do
2003
- @d.filter!(:y => 1)
2004
- @d.sql.should == "SELECT * FROM x WHERE (y = 1)"
2005
- end
2006
-
2007
- specify "should support self-changing filter! with block" do
2008
- @d.filter! {:y == 2}
2009
- @d.sql.should == "SELECT * FROM x WHERE (y = 2)"
2010
- end
2011
-
2012
- specify "should raise for ! methods that don't return a dataset" do
2013
- proc {@d.opts!}.should raise_error(NameError)
2014
- end
2015
-
2016
- specify "should raise for missing methods" do
2017
- proc {@d.xuyz}.should raise_error(NameError)
2018
- proc {@d.xyz!}.should raise_error(NameError)
2019
- proc {@d.xyz?}.should raise_error(NameError)
2020
- end
2021
-
2022
- specify "should support chaining of bang methods" do
2023
- @d.order!(:y)
2024
- @d.filter!(:y => 1)
2025
- @d.sql.should == "SELECT * FROM x WHERE (y = 1) ORDER BY y"
2026
- end
2027
- end
2028
-
2029
- context "Dataset#transform" do
2030
- setup do
2031
- @c = Class.new(Sequel::Dataset) do
2032
- attr_accessor :raw
2033
- attr_accessor :sql
2034
-
2035
- def fetch_rows(sql, &block)
2036
- block[@raw]
2037
- end
2038
-
2039
- def insert(v)
2040
- @sql = insert_sql(v)
2041
- end
2042
-
2043
- def update(v)
2044
- @sql = update_sql(v)
2045
- end
2046
- end
2047
-
2048
- @ds = @c.new(nil).from(:items)
2049
- @ds.transform(:x => [
2050
- proc {|v| Marshal.load(v)},
2051
- proc {|v| Marshal.dump(v)}
2052
- ])
2053
- end
2054
-
2055
- specify "should change the dataset to transform values loaded from the database" do
2056
- @ds.raw = {:x => Marshal.dump([1, 2, 3]), :y => 'hello'}
2057
- @ds.first.should == {:x => [1, 2, 3], :y => 'hello'}
2058
- @ds.raw = {:x => Marshal.dump([1, 2, 3]), :y => 'hello'}
2059
- @ds.all.should == [{:x => [1, 2, 3], :y => 'hello'}]
2060
- end
2061
-
2062
- specify "should change the dataset to transform values saved to the database" do
2063
- @ds.insert(:x => :toast)
2064
- @ds.sql.should == "INSERT INTO items (x) VALUES ('#{Marshal.dump(:toast)}')"
2065
-
2066
- @ds.insert(:y => 'butter')
2067
- @ds.sql.should == "INSERT INTO items (y) VALUES ('butter')"
2068
-
2069
- @ds.update(:x => ['dream'])
2070
- @ds.sql.should == "UPDATE items SET x = '#{Marshal.dump(['dream'])}'"
2071
- end
2072
-
2073
- specify "should be transferred to cloned datasets" do
2074
- @ds2 = @ds.filter(:a => 1)
2075
-
2076
- @ds2.raw = {:x => Marshal.dump([1, 2, 3]), :y => 'hello'}
2077
- @ds2.first.should == {:x => [1, 2, 3], :y => 'hello'}
2078
-
2079
- @ds2.insert(:x => :toast)
2080
- @ds2.sql.should == "INSERT INTO items (x) VALUES ('#{Marshal.dump(:toast)}')"
2081
- end
2082
-
2083
- specify "should work correctly together with set_row_proc" do
2084
- @ds.set_row_proc {|r| r[:z] = r[:x] * 2; r}
2085
- @ds.raw = {:x => Marshal.dump("wow"), :y => 'hello'}
2086
- @ds.first.should == {:x => "wow", :y => 'hello', :z => "wowwow"}
2087
-
2088
- f = nil
2089
- @ds.raw = {:x => Marshal.dump("wow"), :y => 'hello'}
2090
- @ds.each(:naked => true) {|r| f = r}
2091
- f.should == {:x => "wow", :y => 'hello'}
2092
- end
2093
- end
2094
-
2095
- context "Dataset#transform" do
2096
- setup do
2097
- @c = Class.new(Sequel::Dataset) do
2098
- attr_accessor :raw
2099
- attr_accessor :sql
2100
-
2101
- def fetch_rows(sql, &block)
2102
- block[@raw]
2103
- end
2104
-
2105
- def insert(v)
2106
- @sql = insert_sql(v)
2107
- end
2108
-
2109
- def update(v)
2110
- @sql = update_sql(v)
2111
- end
2112
- end
2113
-
2114
- @ds = @c.new(nil).from(:items)
2115
- end
2116
-
2117
- specify "should raise Sequel::Error for invalid transformations" do
2118
- proc {@ds.transform(:x => 'mau')}.should raise_error(Sequel::Error::InvalidTransform)
2119
- proc {@ds.transform(:x => :mau)}.should raise_error(Sequel::Error::InvalidTransform)
2120
- proc {@ds.transform(:x => [])}.should raise_error(Sequel::Error::InvalidTransform)
2121
- proc {@ds.transform(:x => ['mau'])}.should raise_error(Sequel::Error::InvalidTransform)
2122
- proc {@ds.transform(:x => [proc {|v|}, proc {|v|}])}.should_not raise_error(Sequel::Error::InvalidTransform)
2123
- end
2124
-
2125
- specify "should support stock YAML transformation" do
2126
- @ds.transform(:x => :yaml)
2127
-
2128
- @ds.raw = {:x => [1, 2, 3].to_yaml, :y => 'hello'}
2129
- @ds.first.should == {:x => [1, 2, 3], :y => 'hello'}
2130
-
2131
- @ds.insert(:x => :toast)
2132
- @ds.sql.should == "INSERT INTO items (x) VALUES ('#{:toast.to_yaml}')"
2133
- @ds.insert(:y => 'butter')
2134
- @ds.sql.should == "INSERT INTO items (y) VALUES ('butter')"
2135
- @ds.update(:x => ['dream'])
2136
- @ds.sql.should == "UPDATE items SET x = '#{['dream'].to_yaml}'"
2137
-
2138
- @ds2 = @ds.filter(:a => 1)
2139
- @ds2.raw = {:x => [1, 2, 3].to_yaml, :y => 'hello'}
2140
- @ds2.first.should == {:x => [1, 2, 3], :y => 'hello'}
2141
- @ds2.insert(:x => :toast)
2142
- @ds2.sql.should == "INSERT INTO items (x) VALUES ('#{:toast.to_yaml}')"
2143
-
2144
- @ds.set_row_proc {|r| r[:z] = r[:x] * 2; r}
2145
- @ds.raw = {:x => "wow".to_yaml, :y => 'hello'}
2146
- @ds.first.should == {:x => "wow", :y => 'hello', :z => "wowwow"}
2147
- f = nil
2148
- @ds.raw = {:x => "wow".to_yaml, :y => 'hello'}
2149
- @ds.each(:naked => true) {|r| f = r}
2150
- f.should == {:x => "wow", :y => 'hello'}
2151
- end
2152
-
2153
- specify "should support stock Marshal transformation" do
2154
- @ds.transform(:x => :marshal)
2155
-
2156
- @ds.raw = {:x => Marshal.dump([1, 2, 3]), :y => 'hello'}
2157
- @ds.first.should == {:x => [1, 2, 3], :y => 'hello'}
2158
-
2159
- @ds.insert(:x => :toast)
2160
- @ds.sql.should == "INSERT INTO items (x) VALUES ('#{Marshal.dump(:toast)}')"
2161
- @ds.insert(:y => 'butter')
2162
- @ds.sql.should == "INSERT INTO items (y) VALUES ('butter')"
2163
- @ds.update(:x => ['dream'])
2164
- @ds.sql.should == "UPDATE items SET x = '#{Marshal.dump(['dream'])}'"
2165
-
2166
- @ds2 = @ds.filter(:a => 1)
2167
- @ds2.raw = {:x => Marshal.dump([1, 2, 3]), :y => 'hello'}
2168
- @ds2.first.should == {:x => [1, 2, 3], :y => 'hello'}
2169
- @ds2.insert(:x => :toast)
2170
- @ds2.sql.should == "INSERT INTO items (x) VALUES ('#{Marshal.dump(:toast)}')"
2171
-
2172
- @ds.set_row_proc {|r| r[:z] = r[:x] * 2; r}
2173
- @ds.raw = {:x => Marshal.dump("wow"), :y => 'hello'}
2174
- @ds.first.should == {:x => "wow", :y => 'hello', :z => "wowwow"}
2175
- f = nil
2176
- @ds.raw = {:x => Marshal.dump("wow"), :y => 'hello'}
2177
- @ds.each(:naked => true) {|r| f = r}
2178
- f.should == {:x => "wow", :y => 'hello'}
2179
- end
2180
-
2181
- specify "should return self" do
2182
- @ds.transform(:x => :marshal).should be(@ds)
2183
- end
2184
- end
2185
-
2186
- context "Dataset#to_csv" do
2187
- setup do
2188
- @c = Class.new(Sequel::Dataset) do
2189
- attr_accessor :data
2190
- attr_accessor :cols
2191
-
2192
- def fetch_rows(sql, &block)
2193
- @columns = @cols
2194
- @data.each {|r| r.keys = @columns; block[r]}
2195
- end
2196
-
2197
- # naked should return self here because to_csv wants a naked result set.
2198
- def naked
2199
- self
2200
- end
2201
- end
2202
-
2203
- @ds = @c.new(nil).from(:items)
2204
-
2205
- @ds.cols = [:a, :b, :c]
2206
- @ds.data = [
2207
- [1, 2, 3], [4, 5, 6], [7, 8, 9]
2208
- ]
2209
- end
2210
-
2211
- specify "should format a CSV representation of the records" do
2212
- @ds.to_csv.should ==
2213
- "a, b, c\r\n1, 2, 3\r\n4, 5, 6\r\n7, 8, 9\r\n"
2214
- end
2215
-
2216
- specify "should exclude column titles if so specified" do
2217
- @ds.to_csv(false).should ==
2218
- "1, 2, 3\r\n4, 5, 6\r\n7, 8, 9\r\n"
2219
- end
2220
- end
2221
-
2222
- context "Dataset#each_hash" do
2223
- setup do
2224
- @c = Class.new(Sequel::Dataset) do
2225
- def each(&block)
2226
- a = [[1, 2, 3], [4, 5, 6]]
2227
- a.each {|r| r.keys = [:a, :b, :c]; block[r]}
2228
- end
2229
- end
2230
-
2231
- @ds = @c.new(nil).from(:items)
2232
- end
2233
-
2234
- specify "should yield records converted to hashes" do
2235
- hashes = []
2236
- @ds.each_hash {|h| hashes << h}
2237
- hashes.should == [{:a => 1, :b => 2, :c => 3}, {:a => 4, :b => 5, :c => 6}]
2238
- end
2239
- end
2240
-
2241
- context "Dataset magic methods" do
2242
- setup do
2243
- @c = Class.new(Sequel::Dataset) do
2244
- @@sqls = []
2245
-
2246
- def self.sqls; @@sqls; end
2247
-
2248
- def fetch_rows(sql)
2249
- @@sqls << sql
2250
- yield({:a => 1, :b => 2})
2251
- end
2252
- end
2253
-
2254
- @ds = @c.new(nil).from(:items)
2255
- end
2256
-
2257
- specify "should support order_by_xxx" do
2258
- @ds.should_not respond_to(:order_by_name)
2259
- proc {@ds.order_by_name}.should_not raise_error
2260
- @ds.should respond_to(:order_by_name)
2261
- @ds.order_by_name.should be_a_kind_of(@c)
2262
- @ds.order_by_name.sql.should == "SELECT * FROM items ORDER BY name"
2263
- end
2264
-
2265
- specify "should support group_by_xxx" do
2266
- @ds.should_not respond_to(:group_by_name)
2267
- proc {@ds.group_by_name}.should_not raise_error
2268
- @ds.should respond_to(:group_by_name)
2269
- @ds.group_by_name.should be_a_kind_of(@c)
2270
- @ds.group_by_name.sql.should == "SELECT * FROM items GROUP BY name"
2271
- end
2272
-
2273
- specify "should support count_by_xxx" do
2274
- @ds.should_not respond_to(:count_by_name)
2275
- proc {@ds.count_by_name}.should_not raise_error
2276
- @ds.should respond_to(:count_by_name)
2277
- @ds.count_by_name.should be_a_kind_of(@c)
2278
- @ds.count_by_name.sql.should == "SELECT name, count(name) AS count FROM items GROUP BY name ORDER BY count"
2279
- end
2280
-
2281
- specify "should support filter_by_xxx" do
2282
- @ds.should_not respond_to(:filter_by_name)
2283
- proc {@ds.filter_by_name('sharon')}.should_not raise_error
2284
- @ds.should respond_to(:filter_by_name)
2285
- @ds.filter_by_name('sharon').should be_a_kind_of(@c)
2286
- @ds.filter_by_name('sharon').sql.should == "SELECT * FROM items WHERE (name = 'sharon')"
2287
- end
2288
-
2289
- specify "should support all_by_xxx" do
2290
- @ds.should_not respond_to(:all_by_name)
2291
- proc {@ds.all_by_name('sharon')}.should_not raise_error
2292
- @ds.should respond_to(:all_by_name)
2293
- @ds.all_by_name('sharon').should == [{:a => 1, :b => 2}]
2294
- @c.sqls.should == ["SELECT * FROM items WHERE (name = 'sharon')"] * 2
2295
- end
2296
-
2297
- specify "should support find_by_xxx" do
2298
- @ds.should_not respond_to(:find_by_name)
2299
- proc {@ds.find_by_name('sharon')}.should_not raise_error
2300
- @ds.should respond_to(:find_by_name)
2301
- @ds.find_by_name('sharon').should == {:a => 1, :b => 2}
2302
- @c.sqls.should == ["SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"] * 2
2303
- end
2304
-
2305
- specify "should support first_by_xxx" do
2306
- @ds.should_not respond_to(:first_by_name)
2307
- proc {@ds.first_by_name('sharon')}.should_not raise_error
2308
- @ds.should respond_to(:first_by_name)
2309
- @ds.first_by_name('sharon').should == {:a => 1, :b => 2}
2310
- @c.sqls.should == ["SELECT * FROM items ORDER BY name LIMIT 1"] * 2
2311
- end
2312
-
2313
- specify "should support last_by_xxx" do
2314
- @ds.should_not respond_to(:last_by_name)
2315
- proc {@ds.last_by_name('sharon')}.should_not raise_error
2316
- @ds.should respond_to(:last_by_name)
2317
- @ds.last_by_name('sharon').should == {:a => 1, :b => 2}
2318
- @c.sqls.should == ["SELECT * FROM items ORDER BY name DESC LIMIT 1"] * 2
2319
- end
2320
- end
2321
-
2322
- context "Dataset#create_view" do
2323
- setup do
2324
- @dbc = Class.new(Sequel::Database) do
2325
- attr_reader :sqls
2326
-
2327
- def execute(sql)
2328
- @sqls ||= []
2329
- @sqls << sql
2330
- end
2331
- end
2332
- @db = @dbc.new
2333
-
2334
- @ds = @db[:items].order(:abc).filter(:category => 'ruby')
2335
- end
2336
-
2337
- specify "should create a view with the dataset's sql" do
2338
- @ds.create_view(:xyz)
2339
- @db.sqls.should == ["CREATE VIEW xyz AS #{@ds.sql}"]
2340
- end
2341
- end
2342
-
2343
- context "Dataset#create_or_replace_view" do
2344
- setup do
2345
- @dbc = Class.new(Sequel::Database) do
2346
- attr_reader :sqls
2347
-
2348
- def execute(sql)
2349
- @sqls ||= []
2350
- @sqls << sql
2351
- end
2352
- end
2353
- @db = @dbc.new
2354
-
2355
- @ds = @db[:items].order(:abc).filter(:category => 'ruby')
2356
- end
2357
-
2358
- specify "should create a view with the dataset's sql" do
2359
- @ds.create_or_replace_view(:xyz)
2360
- @db.sqls.should == ["CREATE OR REPLACE VIEW xyz AS #{@ds.sql}"]
2361
- end
2362
- end
2363
-
2364
- context "Dataset#update_sql" do
2365
- setup do
2366
- @ds = Sequel::Dataset.new(nil).from(:items)
2367
- end
2368
-
2369
- specify "should accept strings" do
2370
- @ds.update_sql("a = b").should == "UPDATE items SET a = b"
2371
- end
2372
-
2373
- specify "should accept hash with string keys" do
2374
- @ds.update_sql('c' => 'd').should == "UPDATE items SET c = 'd'"
2375
- end
2376
-
2377
- specify "should accept array subscript references" do
2378
- @ds.update_sql((:day|1) => 'd').should == "UPDATE items SET day[1] = 'd'"
2379
- end
2380
-
2381
- end