sequel_core 1.5.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +116 -0
- data/COPYING +19 -19
- data/README +83 -32
- data/Rakefile +9 -20
- data/bin/sequel +43 -112
- data/doc/cheat_sheet.rdoc +225 -0
- data/doc/dataset_filtering.rdoc +257 -0
- data/lib/sequel_core/adapters/adapter_skeleton.rb +4 -2
- data/lib/sequel_core/adapters/ado.rb +3 -1
- data/lib/sequel_core/adapters/db2.rb +4 -2
- data/lib/sequel_core/adapters/dbi.rb +127 -113
- data/lib/sequel_core/adapters/informix.rb +4 -2
- data/lib/sequel_core/adapters/jdbc.rb +5 -3
- data/lib/sequel_core/adapters/mysql.rb +112 -46
- data/lib/sequel_core/adapters/odbc.rb +5 -7
- data/lib/sequel_core/adapters/odbc_mssql.rb +12 -3
- data/lib/sequel_core/adapters/openbase.rb +3 -1
- data/lib/sequel_core/adapters/oracle.rb +11 -9
- data/lib/sequel_core/adapters/postgres.rb +261 -262
- data/lib/sequel_core/adapters/sqlite.rb +72 -22
- data/lib/sequel_core/connection_pool.rb +140 -73
- data/lib/sequel_core/core_ext.rb +201 -66
- data/lib/sequel_core/core_sql.rb +123 -153
- data/lib/sequel_core/database/schema.rb +156 -0
- data/lib/sequel_core/database.rb +321 -338
- data/lib/sequel_core/dataset/callback.rb +11 -12
- data/lib/sequel_core/dataset/convenience.rb +213 -240
- data/lib/sequel_core/dataset/pagination.rb +58 -43
- data/lib/sequel_core/dataset/parse_tree_sequelizer.rb +331 -0
- data/lib/sequel_core/dataset/query.rb +41 -0
- data/lib/sequel_core/dataset/schema.rb +15 -0
- data/lib/sequel_core/dataset/sequelizer.rb +41 -373
- data/lib/sequel_core/dataset/sql.rb +741 -632
- data/lib/sequel_core/dataset.rb +183 -168
- data/lib/sequel_core/deprecated.rb +1 -169
- data/lib/sequel_core/exceptions.rb +24 -19
- data/lib/sequel_core/migration.rb +44 -52
- data/lib/sequel_core/object_graph.rb +43 -42
- data/lib/sequel_core/pretty_table.rb +71 -76
- data/lib/sequel_core/schema/generator.rb +163 -105
- data/lib/sequel_core/schema/sql.rb +250 -93
- data/lib/sequel_core/schema.rb +2 -8
- data/lib/sequel_core/sql.rb +394 -0
- data/lib/sequel_core/worker.rb +37 -27
- data/lib/sequel_core.rb +99 -45
- data/spec/adapters/informix_spec.rb +0 -1
- data/spec/adapters/mysql_spec.rb +177 -124
- data/spec/adapters/oracle_spec.rb +0 -1
- data/spec/adapters/postgres_spec.rb +98 -58
- data/spec/adapters/sqlite_spec.rb +45 -4
- data/spec/blockless_filters_spec.rb +269 -0
- data/spec/connection_pool_spec.rb +21 -18
- data/spec/core_ext_spec.rb +169 -19
- data/spec/core_sql_spec.rb +56 -49
- data/spec/database_spec.rb +78 -17
- data/spec/dataset_spec.rb +300 -428
- data/spec/migration_spec.rb +1 -1
- data/spec/object_graph_spec.rb +5 -11
- data/spec/rcov.opts +1 -1
- data/spec/schema_generator_spec.rb +16 -4
- data/spec/schema_spec.rb +89 -10
- data/spec/sequelizer_spec.rb +56 -56
- data/spec/spec.opts +0 -5
- data/spec/spec_config.rb +7 -0
- data/spec/spec_config.rb.example +5 -5
- data/spec/spec_helper.rb +6 -0
- data/spec/worker_spec.rb +1 -1
- metadata +78 -63
data/spec/dataset_spec.rb
CHANGED
@@ -66,7 +66,7 @@ context "Dataset#clone" do
|
|
66
66
|
specify "should deep-copy the dataset opts" do
|
67
67
|
@clone = @dataset.clone
|
68
68
|
|
69
|
-
@clone.opts.should_not
|
69
|
+
@clone.opts.should_not equal(@dataset.opts)
|
70
70
|
@dataset.filter!(:a => 'b')
|
71
71
|
@clone.opts[:filter].should be_nil
|
72
72
|
end
|
@@ -162,7 +162,9 @@ context "A simple dataset" do
|
|
162
162
|
specify "should format an update statement" do
|
163
163
|
@dataset.update_sql(:name => 'abc').should ==
|
164
164
|
"UPDATE test SET name = 'abc'"
|
165
|
+
end
|
165
166
|
|
167
|
+
pt_specify "should format an update statement with block" do
|
166
168
|
@dataset.update_sql {:x << :y}.should ==
|
167
169
|
"UPDATE test SET x = y"
|
168
170
|
end
|
@@ -195,23 +197,23 @@ context "Dataset#where" do
|
|
195
197
|
setup do
|
196
198
|
@dataset = Sequel::Dataset.new(nil).from(:test)
|
197
199
|
@d1 = @dataset.where(:region => 'Asia')
|
198
|
-
@d2 = @dataset.where('
|
199
|
-
@d3 = @dataset.where("
|
200
|
+
@d2 = @dataset.where('region = ?', 'Asia')
|
201
|
+
@d3 = @dataset.where("a = 1")
|
200
202
|
end
|
201
203
|
|
202
204
|
specify "should work with hashes" do
|
203
205
|
@dataset.where(:name => 'xyz', :price => 342).select_sql.
|
204
|
-
should match(/WHERE \(name = 'xyz'\) AND \(price = 342\)|WHERE \(price = 342\) AND \(name = 'xyz'\)/)
|
206
|
+
should match(/WHERE \(\(name = 'xyz'\) AND \(price = 342\)\)|WHERE \(\(price = 342\) AND \(name = 'xyz'\)\)/)
|
205
207
|
end
|
206
208
|
|
207
209
|
specify "should work with arrays (ala ActiveRecord)" do
|
208
|
-
@dataset.where('price < ? AND id in
|
209
|
-
"SELECT * FROM test WHERE price < 100 AND id in (1, 2, 3)"
|
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))"
|
210
212
|
end
|
211
213
|
|
212
214
|
specify "should work with strings (custom SQL expressions)" do
|
213
215
|
@dataset.where('(a = 1 AND b = 2)').select_sql.should ==
|
214
|
-
"SELECT * FROM test WHERE (a = 1 AND b = 2)"
|
216
|
+
"SELECT * FROM test WHERE ((a = 1 AND b = 2))"
|
215
217
|
end
|
216
218
|
|
217
219
|
specify "should affect select, delete and update statements" do
|
@@ -232,45 +234,46 @@ context "Dataset#where" do
|
|
232
234
|
specify "should be composable using AND operator (for scoping)" do
|
233
235
|
# hashes are merged, no problem
|
234
236
|
@d1.where(:size => 'big').select_sql.should ==
|
235
|
-
"SELECT * FROM test WHERE (region = 'Asia') AND (size = 'big')"
|
237
|
+
"SELECT * FROM test WHERE ((region = 'Asia') AND (size = 'big'))"
|
236
238
|
|
237
239
|
# hash and string
|
238
240
|
@d1.where('population > 1000').select_sql.should ==
|
239
|
-
"SELECT * FROM test WHERE (region = 'Asia') AND (population > 1000)"
|
241
|
+
"SELECT * FROM test WHERE ((region = 'Asia') AND (population > 1000))"
|
240
242
|
@d1.where('(a > 1) OR (b < 2)').select_sql.should ==
|
241
|
-
"SELECT * FROM test WHERE (region = 'Asia') AND ((a > 1) OR (b < 2))"
|
243
|
+
"SELECT * FROM test WHERE ((region = 'Asia') AND ((a > 1) OR (b < 2)))"
|
242
244
|
|
243
245
|
# hash and array
|
244
|
-
@d1.where('
|
245
|
-
"SELECT * FROM test WHERE (region = 'Asia') AND (GDP > 1000)"
|
246
|
+
@d1.where('GDP > ?', 1000).select_sql.should ==
|
247
|
+
"SELECT * FROM test WHERE ((region = 'Asia') AND (GDP > 1000))"
|
246
248
|
|
247
249
|
# array and array
|
248
|
-
@d2.where('
|
249
|
-
"SELECT * FROM test WHERE (region = 'Asia') AND (GDP > 1000)"
|
250
|
+
@d2.where('GDP > ?', 1000).select_sql.should ==
|
251
|
+
"SELECT * FROM test WHERE ((region = 'Asia') AND (GDP > 1000))"
|
250
252
|
|
251
253
|
# array and hash
|
252
254
|
@d2.where(:name => ['Japan', 'China']).select_sql.should ==
|
253
|
-
"SELECT * FROM test WHERE (region = 'Asia') AND (name IN ('Japan', 'China'))"
|
255
|
+
"SELECT * FROM test WHERE ((region = 'Asia') AND (name IN ('Japan', 'China')))"
|
254
256
|
|
255
257
|
# array and string
|
256
258
|
@d2.where('GDP > ?').select_sql.should ==
|
257
|
-
"SELECT * FROM test WHERE (region = 'Asia') AND (GDP > ?)"
|
259
|
+
"SELECT * FROM test WHERE ((region = 'Asia') AND (GDP > ?))"
|
258
260
|
|
259
261
|
# string and string
|
260
262
|
@d3.where('b = 2').select_sql.should ==
|
261
|
-
"SELECT * FROM test WHERE (a = 1) AND (b = 2)"
|
263
|
+
"SELECT * FROM test WHERE ((a = 1) AND (b = 2))"
|
262
264
|
|
263
265
|
# string and hash
|
264
266
|
@d3.where(:c => 3).select_sql.should ==
|
265
|
-
"SELECT * FROM test WHERE (a = 1) AND (c = 3)"
|
267
|
+
"SELECT * FROM test WHERE ((a = 1) AND (c = 3))"
|
266
268
|
|
267
269
|
# string and array
|
268
|
-
@d3.where('
|
269
|
-
"SELECT * FROM test WHERE (a = 1) AND (d = 4)"
|
270
|
+
@d3.where('d = ?', 4).select_sql.should ==
|
271
|
+
"SELECT * FROM test WHERE ((a = 1) AND (d = 4))"
|
272
|
+
end
|
270
273
|
|
271
|
-
|
272
|
-
@d3.where
|
273
|
-
"SELECT * FROM test WHERE (a = 1) AND (e < 5)"
|
274
|
+
pt_specify "should be composable using AND operator (for scoping) with block" do
|
275
|
+
@d3.where{:e < 5}.select_sql.should ==
|
276
|
+
"SELECT * FROM test WHERE ((a = 1) AND (e < 5))"
|
274
277
|
end
|
275
278
|
|
276
279
|
specify "should raise if the dataset is grouped" do
|
@@ -281,21 +284,22 @@ context "Dataset#where" do
|
|
281
284
|
|
282
285
|
specify "should accept ranges" do
|
283
286
|
@dataset.filter(:id => 4..7).sql.should ==
|
284
|
-
'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
|
287
|
+
'SELECT * FROM test WHERE ((id >= 4) AND (id <= 7))'
|
285
288
|
@dataset.filter(:id => 4...7).sql.should ==
|
286
|
-
'SELECT * FROM test WHERE (id >= 4 AND id < 7)'
|
289
|
+
'SELECT * FROM test WHERE ((id >= 4) AND (id < 7))'
|
287
290
|
|
291
|
+
@dataset.filter(:table__id => 4..7).sql.should ==
|
292
|
+
'SELECT * FROM test WHERE ((table.id >= 4) AND (table.id <= 7))'
|
293
|
+
@dataset.filter(:table__id => 4...7).sql.should ==
|
294
|
+
'SELECT * FROM test WHERE ((table.id >= 4) AND (table.id < 7))'
|
295
|
+
end
|
296
|
+
|
297
|
+
pt_specify "should accept ranges with a block" do
|
288
298
|
@dataset.filter {:id == (4..7)}.sql.should ==
|
289
299
|
'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
|
290
|
-
|
291
300
|
@dataset.filter {:id.in?(4..7)}.sql.should ==
|
292
301
|
'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
|
293
302
|
|
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
303
|
@dataset.filter {:table__id == (4..7)}.sql.should ==
|
300
304
|
'SELECT * FROM test WHERE (table.id >= 4 AND table.id <= 7)'
|
301
305
|
@dataset.filter {:table__id.in?(4..7)}.sql.should ==
|
@@ -305,7 +309,9 @@ context "Dataset#where" do
|
|
305
309
|
specify "should accept nil" do
|
306
310
|
@dataset.filter(:owner_id => nil).sql.should ==
|
307
311
|
'SELECT * FROM test WHERE (owner_id IS NULL)'
|
312
|
+
end
|
308
313
|
|
314
|
+
pt_specify "should accept nil with a block" do
|
309
315
|
@dataset.filter{:owner_id.nil?}.sql.should ==
|
310
316
|
'SELECT * FROM test WHERE (owner_id IS NULL)'
|
311
317
|
end
|
@@ -313,19 +319,19 @@ context "Dataset#where" do
|
|
313
319
|
specify "should accept a subquery" do
|
314
320
|
# select all countries that have GDP greater than the average for Asia
|
315
321
|
@dataset.filter('gdp > ?', @d1.select(:avg[:gdp])).sql.should ==
|
316
|
-
"SELECT * FROM test WHERE gdp > (SELECT avg(gdp) FROM test WHERE (region = 'Asia'))"
|
322
|
+
"SELECT * FROM test WHERE (gdp > (SELECT avg(gdp) FROM test WHERE (region = 'Asia')))"
|
317
323
|
|
318
324
|
@dataset.filter(:id => @d1.select(:id)).sql.should ==
|
319
325
|
"SELECT * FROM test WHERE (id IN (SELECT id FROM test WHERE (region = 'Asia')))"
|
320
326
|
end
|
321
327
|
|
322
328
|
specify "should accept a subquery for an EXISTS clause" do
|
323
|
-
a = @dataset.filter
|
329
|
+
a = @dataset.filter(:price < 100)
|
324
330
|
@dataset.filter(a.exists).sql.should ==
|
325
|
-
'SELECT * FROM test WHERE EXISTS (SELECT * FROM test WHERE (price < 100))'
|
331
|
+
'SELECT * FROM test WHERE (EXISTS (SELECT * FROM test WHERE (price < 100)))'
|
326
332
|
end
|
327
333
|
|
328
|
-
|
334
|
+
pt_specify "should accept proc expressions" do
|
329
335
|
d = @d1.select(:avg[:gdp])
|
330
336
|
@dataset.filter {:gdp > d}.sql.should ==
|
331
337
|
"SELECT * FROM test WHERE (gdp > (SELECT avg(gdp) FROM test WHERE (region = 'Asia')))"
|
@@ -384,24 +390,27 @@ context "Dataset#or" do
|
|
384
390
|
|
385
391
|
specify "should add an alternative expression to the where clause" do
|
386
392
|
@d1.or(:y => 2).sql.should ==
|
387
|
-
'SELECT * FROM test WHERE (x = 1) OR (y = 2)'
|
393
|
+
'SELECT * FROM test WHERE ((x = 1) OR (y = 2))'
|
388
394
|
end
|
389
395
|
|
390
396
|
specify "should accept all forms of filters" do
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
+
@d1.or('y > ?', 2).sql.should ==
|
398
|
+
'SELECT * FROM test WHERE ((x = 1) OR (y > 2))'
|
399
|
+
@d1.or(:yy > 3).sql.should ==
|
400
|
+
'SELECT * FROM test WHERE ((x = 1) OR (yy > 3))'
|
401
|
+
end
|
402
|
+
|
403
|
+
pt_specify "should accept blocks passed to filter" do
|
404
|
+
@d1.or{:yy > 3}.sql.should ==
|
405
|
+
'SELECT * FROM test WHERE ((x = 1) OR (yy > 3))'
|
397
406
|
end
|
398
407
|
|
399
408
|
specify "should correctly add parens to give predictable results" do
|
400
409
|
@d1.filter(:y => 2).or(:z => 3).sql.should ==
|
401
|
-
'SELECT * FROM test WHERE ((x = 1) AND (y = 2)) OR (z = 3)'
|
410
|
+
'SELECT * FROM test WHERE (((x = 1) AND (y = 2)) OR (z = 3))'
|
402
411
|
|
403
412
|
@d1.or(:y => 2).filter(:z => 3).sql.should ==
|
404
|
-
'SELECT * FROM test WHERE ((x = 1) OR (y = 2)) AND (z = 3)'
|
413
|
+
'SELECT * FROM test WHERE (((x = 1) OR (y = 2)) AND (z = 3))'
|
405
414
|
end
|
406
415
|
end
|
407
416
|
|
@@ -420,24 +429,28 @@ context "Dataset#and" do
|
|
420
429
|
|
421
430
|
specify "should add an alternative expression to the where clause" do
|
422
431
|
@d1.and(:y => 2).sql.should ==
|
423
|
-
'SELECT * FROM test WHERE (x = 1) AND (y = 2)'
|
432
|
+
'SELECT * FROM test WHERE ((x = 1) AND (y = 2))'
|
424
433
|
end
|
425
434
|
|
426
435
|
specify "should accept all forms of filters" do
|
427
436
|
# probably not exhaustive, but good enough
|
428
|
-
@d1.and('
|
429
|
-
'SELECT * FROM test WHERE (x = 1) AND (y > 2)'
|
437
|
+
@d1.and('y > ?', 2).sql.should ==
|
438
|
+
'SELECT * FROM test WHERE ((x = 1) AND (y > 2))'
|
439
|
+
@d1.and(:yy > 3).sql.should ==
|
440
|
+
'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
|
441
|
+
end
|
430
442
|
|
431
|
-
|
432
|
-
|
443
|
+
pt_specify "should accept blocks passed to filter" do
|
444
|
+
@d1.and {:yy > 3}.sql.should ==
|
445
|
+
'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
|
433
446
|
end
|
434
447
|
|
435
448
|
specify "should correctly add parens to give predictable results" do
|
436
449
|
@d1.or(:y => 2).and(:z => 3).sql.should ==
|
437
|
-
'SELECT * FROM test WHERE ((x = 1) OR (y = 2)) AND (z = 3)'
|
450
|
+
'SELECT * FROM test WHERE (((x = 1) OR (y = 2)) AND (z = 3))'
|
438
451
|
|
439
452
|
@d1.and(:y => 2).or(:z => 3).sql.should ==
|
440
|
-
'SELECT * FROM test WHERE ((x = 1) AND (y = 2)) OR (z = 3)'
|
453
|
+
'SELECT * FROM test WHERE (((x = 1) AND (y = 2)) OR (z = 3))'
|
441
454
|
end
|
442
455
|
end
|
443
456
|
|
@@ -448,33 +461,51 @@ context "Dataset#exclude" do
|
|
448
461
|
|
449
462
|
specify "should correctly include the NOT operator when one condition is given" do
|
450
463
|
@dataset.exclude(:region=>'Asia').select_sql.should ==
|
451
|
-
"SELECT * FROM test WHERE (
|
464
|
+
"SELECT * FROM test WHERE (region != 'Asia')"
|
452
465
|
end
|
453
466
|
|
454
467
|
specify "should take multiple conditions as a hash and express the logic correctly in SQL" do
|
455
468
|
@dataset.exclude(:region => 'Asia', :name => 'Japan').select_sql.
|
456
|
-
should match(Regexp.union(/WHERE \(
|
457
|
-
/WHERE \(
|
469
|
+
should match(Regexp.union(/WHERE \(\(region != 'Asia'\) AND \(name != 'Japan'\)\)/,
|
470
|
+
/WHERE \(\(name != 'Japan'\) AND \(region != 'Asia'\)\)/))
|
458
471
|
end
|
459
472
|
|
460
473
|
specify "should parenthesize a single string condition correctly" do
|
461
474
|
@dataset.exclude("region = 'Asia' AND name = 'Japan'").select_sql.should ==
|
462
|
-
"SELECT * FROM test WHERE
|
475
|
+
"SELECT * FROM test WHERE NOT (region = 'Asia' AND name = 'Japan')"
|
463
476
|
end
|
464
477
|
|
465
478
|
specify "should parenthesize an array condition correctly" do
|
466
479
|
@dataset.exclude('region = ? AND name = ?', 'Asia', 'Japan').select_sql.should ==
|
467
|
-
"SELECT * FROM test WHERE
|
480
|
+
"SELECT * FROM test WHERE NOT (region = 'Asia' AND name = 'Japan')"
|
468
481
|
end
|
469
482
|
|
470
483
|
specify "should correctly parenthesize when it is used twice" do
|
471
484
|
@dataset.exclude(:region => 'Asia').exclude(:name => 'Japan').select_sql.should ==
|
472
|
-
"SELECT * FROM test WHERE (
|
485
|
+
"SELECT * FROM test WHERE ((region != 'Asia') AND (name != 'Japan'))"
|
473
486
|
end
|
474
487
|
|
475
|
-
|
488
|
+
pt_specify "should support proc expressions" do
|
476
489
|
@dataset.exclude {:id == (6...12)}.sql.should ==
|
477
|
-
'SELECT * FROM test WHERE
|
490
|
+
'SELECT * FROM test WHERE NOT (id >= 6 AND id < 12)'
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
context "Dataset#invert" do
|
495
|
+
setup do
|
496
|
+
@d = Sequel::Dataset.new(nil).from(:test)
|
497
|
+
end
|
498
|
+
|
499
|
+
specify "should raise error if the dataset is not filtered" do
|
500
|
+
proc{@d.invert}.should raise_error(Sequel::Error)
|
501
|
+
end
|
502
|
+
|
503
|
+
specify "should invert current filter if dataset is filtered" do
|
504
|
+
@d.filter(:x).invert.sql.should == 'SELECT * FROM test WHERE NOT x'
|
505
|
+
end
|
506
|
+
|
507
|
+
specify "should invert both having and where if both are preset" do
|
508
|
+
@d.filter(:x).group(:x).having(:x).invert.sql.should == 'SELECT * FROM test WHERE NOT x GROUP BY x HAVING NOT x'
|
478
509
|
end
|
479
510
|
end
|
480
511
|
|
@@ -493,17 +524,17 @@ context "Dataset#having" do
|
|
493
524
|
|
494
525
|
specify "should affect select statements" do
|
495
526
|
@d1.select_sql.should ==
|
496
|
-
"SELECT #{@columns} FROM test GROUP BY region HAVING sum(population) > 10"
|
527
|
+
"SELECT #{@columns} FROM test GROUP BY region HAVING (sum(population) > 10)"
|
497
528
|
end
|
498
529
|
|
499
|
-
|
530
|
+
pt_specify "should support proc expressions" do
|
500
531
|
@grouped.having {:sum[:population] > 10}.sql.should ==
|
501
532
|
"SELECT #{@columns} FROM test GROUP BY region HAVING (sum(population) > 10)"
|
502
533
|
end
|
503
534
|
|
504
535
|
specify "should work with and on the having clause" do
|
505
|
-
@grouped.having
|
506
|
-
"SELECT #{@columns} FROM test GROUP BY region HAVING (a > 1) AND (b < 2)"
|
536
|
+
@grouped.having( :a > 1 ).and( :b < 2 ).sql.should ==
|
537
|
+
"SELECT #{@columns} FROM test GROUP BY region HAVING ((a > 1) AND (b < 2))"
|
507
538
|
end
|
508
539
|
end
|
509
540
|
|
@@ -528,7 +559,7 @@ context "a grouped dataset" do
|
|
528
559
|
specify "should format the right statement for counting (as a subquery)" do
|
529
560
|
db = MockDatabase.new
|
530
561
|
db[:test].select(:name).group(:name).count
|
531
|
-
db.sqls.should == ["SELECT COUNT(*) FROM (SELECT name FROM test GROUP BY name) t1"]
|
562
|
+
db.sqls.should == ["SELECT COUNT(*) FROM (SELECT name FROM test GROUP BY name) t1 LIMIT 1"]
|
532
563
|
end
|
533
564
|
end
|
534
565
|
|
@@ -551,6 +582,14 @@ context "Dataset#group_by" do
|
|
551
582
|
end
|
552
583
|
end
|
553
584
|
|
585
|
+
context "Dataset#as" do
|
586
|
+
specify "should set up an alias" do
|
587
|
+
dataset = Sequel::Dataset.new(nil).from(:test)
|
588
|
+
dataset.select(dataset.limit(1).select(:name).as(:n)).sql.should == \
|
589
|
+
'SELECT (SELECT name FROM test LIMIT 1) AS n FROM test'
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
554
593
|
context "Dataset#literal" do
|
555
594
|
setup do
|
556
595
|
@dataset = Sequel::Dataset.new(nil).from(:test)
|
@@ -576,9 +615,9 @@ context "Dataset#literal" do
|
|
576
615
|
end
|
577
616
|
|
578
617
|
specify "should literalize an array properly" do
|
579
|
-
@dataset.literal([]).should == "NULL"
|
580
|
-
@dataset.literal([1, 'abc', 3]).should == "1, 'abc', 3"
|
581
|
-
@dataset.literal([1, "a'b''c", 3]).should == "1, 'a''b''''c', 3"
|
618
|
+
@dataset.literal([]).should == "(NULL)"
|
619
|
+
@dataset.literal([1, 'abc', 3]).should == "(1, 'abc', 3)"
|
620
|
+
@dataset.literal([1, "a'b''c", 3]).should == "(1, 'a''b''''c', 3)"
|
582
621
|
end
|
583
622
|
|
584
623
|
specify "should literalize symbols as column references" do
|
@@ -658,9 +697,9 @@ context "Dataset#from" do
|
|
658
697
|
"SELECT * FROM (SELECT * FROM a GROUP BY b) c"
|
659
698
|
end
|
660
699
|
|
661
|
-
specify "should use
|
700
|
+
specify "should always use a subquery if given a dataset" do
|
662
701
|
@dataset.from(@dataset.from(:a)).select_sql.should ==
|
663
|
-
"SELECT * FROM a"
|
702
|
+
"SELECT * FROM (SELECT * FROM a) t1"
|
664
703
|
end
|
665
704
|
|
666
705
|
specify "should raise if no source is given" do
|
@@ -671,8 +710,8 @@ context "Dataset#from" do
|
|
671
710
|
@dataset.from(:abc[:def]).select_sql.should ==
|
672
711
|
"SELECT * FROM abc(def)"
|
673
712
|
|
674
|
-
@dataset.from(:a
|
675
|
-
"SELECT * FROM a
|
713
|
+
@dataset.from(:a[:i]).select_sql.should ==
|
714
|
+
"SELECT * FROM a(i)"
|
676
715
|
|
677
716
|
@dataset.from(:generate_series[1, 2].as(:a[:i])).select_sql.should ==
|
678
717
|
"SELECT * FROM generate_series(1, 2) AS a(i)"
|
@@ -794,6 +833,17 @@ context "Dataset#order" do
|
|
794
833
|
end
|
795
834
|
end
|
796
835
|
|
836
|
+
context "Dataset#unfiltered" do
|
837
|
+
setup do
|
838
|
+
@dataset = Sequel::Dataset.new(nil).from(:test)
|
839
|
+
end
|
840
|
+
|
841
|
+
specify "should remove filtering from the dataset" do
|
842
|
+
@dataset.filter(:score=>1).unfiltered.sql.should ==
|
843
|
+
'SELECT * FROM test'
|
844
|
+
end
|
845
|
+
end
|
846
|
+
|
797
847
|
context "Dataset#unordered" do
|
798
848
|
setup do
|
799
849
|
@dataset = Sequel::Dataset.new(nil).from(:test)
|
@@ -923,6 +973,15 @@ context "Dataset#limit" do
|
|
923
973
|
@dataset.limit(6, 10).sql.should ==
|
924
974
|
'SELECT * FROM (select * from cccc) t1 LIMIT 6 OFFSET 10'
|
925
975
|
end
|
976
|
+
|
977
|
+
specify "should raise an error if an invalid limit or offset is used" do
|
978
|
+
proc{@dataset.limit(-1)}.should raise_error(Sequel::Error)
|
979
|
+
proc{@dataset.limit(0)}.should raise_error(Sequel::Error)
|
980
|
+
proc{@dataset.limit(1)}.should_not raise_error(Sequel::Error)
|
981
|
+
proc{@dataset.limit(1, -1)}.should raise_error(Sequel::Error)
|
982
|
+
proc{@dataset.limit(1, 0)}.should_not raise_error(Sequel::Error)
|
983
|
+
proc{@dataset.limit(1, 1)}.should_not raise_error(Sequel::Error)
|
984
|
+
end
|
926
985
|
end
|
927
986
|
|
928
987
|
context "Dataset#naked" do
|
@@ -947,14 +1006,18 @@ context "Dataset#qualified_column_name" do
|
|
947
1006
|
@dataset = Sequel::Dataset.new(nil).from(:test)
|
948
1007
|
end
|
949
1008
|
|
950
|
-
specify "should return the
|
951
|
-
@dataset.send(:qualified_column_name, '
|
952
|
-
@dataset.send(:qualified_column_name,
|
1009
|
+
specify "should return the literal value if not given a symbol" do
|
1010
|
+
@dataset.literal(@dataset.send(:qualified_column_name, 'ccc__b', :items)).should == "'ccc__b'"
|
1011
|
+
@dataset.literal(@dataset.send(:qualified_column_name, 3, :items)).should == '3'
|
1012
|
+
@dataset.literal(@dataset.send(:qualified_column_name, 'a'.lit, :items)).should == 'a'
|
953
1013
|
end
|
954
1014
|
|
955
|
-
specify "should qualify the column with the supplied table name" do
|
956
|
-
@dataset.send(:qualified_column_name,
|
957
|
-
|
1015
|
+
specify "should qualify the column with the supplied table name if given an unqualified symbol" do
|
1016
|
+
@dataset.literal(@dataset.send(:qualified_column_name, :b1, :items)).should == 'items.b1'
|
1017
|
+
end
|
1018
|
+
|
1019
|
+
specify "should not changed the qualifed column's table if given a qualified symbol" do
|
1020
|
+
@dataset.literal(@dataset.send(:qualified_column_name, :ccc__b, :items)).should == 'ccc.b'
|
958
1021
|
end
|
959
1022
|
end
|
960
1023
|
|
@@ -983,7 +1046,7 @@ context "Dataset#map" do
|
|
983
1046
|
end
|
984
1047
|
|
985
1048
|
specify "should return the complete dataset values if nothing is given" do
|
986
|
-
@d.map.should == DummyDataset::VALUES
|
1049
|
+
@d.map.to_a.should == DummyDataset::VALUES
|
987
1050
|
end
|
988
1051
|
end
|
989
1052
|
|
@@ -1035,7 +1098,7 @@ context "Dataset#count" do
|
|
1035
1098
|
|
1036
1099
|
specify "should format SQL properly" do
|
1037
1100
|
@dataset.count.should == 1
|
1038
|
-
@c.sql.should == 'SELECT COUNT(*) FROM test'
|
1101
|
+
@c.sql.should == 'SELECT COUNT(*) FROM test LIMIT 1'
|
1039
1102
|
end
|
1040
1103
|
|
1041
1104
|
specify "should be aliased by #size" do
|
@@ -1043,14 +1106,14 @@ context "Dataset#count" do
|
|
1043
1106
|
end
|
1044
1107
|
|
1045
1108
|
specify "should include the where clause if it's there" do
|
1046
|
-
@dataset.filter
|
1047
|
-
@c.sql.should == 'SELECT COUNT(*) FROM test WHERE (abc < 30)'
|
1109
|
+
@dataset.filter(:abc < 30).count.should == 1
|
1110
|
+
@c.sql.should == 'SELECT COUNT(*) FROM test WHERE (abc < 30) LIMIT 1'
|
1048
1111
|
end
|
1049
1112
|
|
1050
1113
|
specify "should count properly for datasets with fixed sql" do
|
1051
1114
|
@dataset.opts[:sql] = "select abc from xyz"
|
1052
1115
|
@dataset.count.should == 1
|
1053
|
-
@c.sql.should == "SELECT COUNT(*) FROM (select abc from xyz) t1"
|
1116
|
+
@c.sql.should == "SELECT COUNT(*) FROM (select abc from xyz) t1 LIMIT 1"
|
1054
1117
|
end
|
1055
1118
|
end
|
1056
1119
|
|
@@ -1106,7 +1169,7 @@ context "Dataset#empty?" do
|
|
1106
1169
|
@dataset = Sequel::Dataset.new(@db).from(:test)
|
1107
1170
|
|
1108
1171
|
@dataset.should_not be_empty
|
1109
|
-
@db.sqls.last.should == 'SELECT 1 WHERE EXISTS (SELECT * FROM test)'
|
1172
|
+
@db.sqls.last.should == 'SELECT 1 WHERE (EXISTS (SELECT * FROM test)) LIMIT 1'
|
1110
1173
|
|
1111
1174
|
@db.meta_def(:dataset) do
|
1112
1175
|
ds = $cccc.new(self)
|
@@ -1121,26 +1184,32 @@ end
|
|
1121
1184
|
context "Dataset#join_table" do
|
1122
1185
|
setup do
|
1123
1186
|
@d = Sequel::Dataset.new(nil).from(:items)
|
1187
|
+
@d.quote_identifiers = true
|
1124
1188
|
end
|
1125
1189
|
|
1126
1190
|
specify "should format the JOIN clause properly" do
|
1127
1191
|
@d.join_table(:left_outer, :categories, :category_id => :id).sql.should ==
|
1128
|
-
'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.category_id = items.id)'
|
1192
|
+
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1193
|
+
end
|
1194
|
+
|
1195
|
+
specify "should handle multiple conditions on the same join table column" do
|
1196
|
+
@d.join_table(:left_outer, :categories, [[:category_id, :id], [:category_id, 0..100]]).sql.should ==
|
1197
|
+
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON (("categories"."category_id" = "items"."id") AND (("categories"."category_id" >= 0) AND ("categories"."category_id" <= 100)))'
|
1129
1198
|
end
|
1130
1199
|
|
1131
1200
|
specify "should include WHERE clause if applicable" do
|
1132
|
-
@d.filter
|
1133
|
-
'SELECT * FROM items RIGHT OUTER JOIN categories ON (categories.category_id = items.id) WHERE (price < 100)'
|
1201
|
+
@d.filter(:price < 100).join_table(:right_outer, :categories, :category_id => :id).sql.should ==
|
1202
|
+
'SELECT * FROM "items" RIGHT OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id") WHERE ("price" < 100)'
|
1134
1203
|
end
|
1135
1204
|
|
1136
1205
|
specify "should include ORDER BY clause if applicable" do
|
1137
1206
|
@d.order(:stamp).join_table(:full_outer, :categories, :category_id => :id).sql.should ==
|
1138
|
-
'SELECT * FROM items FULL OUTER JOIN categories ON (categories.category_id = items.id) ORDER BY stamp'
|
1207
|
+
'SELECT * FROM "items" FULL OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id") ORDER BY "stamp"'
|
1139
1208
|
end
|
1140
1209
|
|
1141
1210
|
specify "should support multiple joins" do
|
1142
1211
|
@d.join_table(:inner, :b, :items_id).join_table(:left_outer, :c, :b_id => :b__id).sql.should ==
|
1143
|
-
'SELECT * FROM items INNER JOIN b ON (b.items_id = items.id) LEFT OUTER JOIN c ON (c.b_id = b.id)'
|
1212
|
+
'SELECT * FROM "items" INNER JOIN "b" ON ("b"."items_id" = "items"."id") LEFT OUTER JOIN "c" ON ("c"."b_id" = "b"."id")'
|
1144
1213
|
end
|
1145
1214
|
|
1146
1215
|
specify "should use id as implicit relation primary key if omitted" do
|
@@ -1149,47 +1218,47 @@ context "Dataset#join_table" do
|
|
1149
1218
|
|
1150
1219
|
# when doing multiple joins, id should be qualified using the last joined table
|
1151
1220
|
@d.join_table(:right_outer, :b, :items_id).join_table(:full_outer, :c, :b_id).sql.should ==
|
1152
|
-
'SELECT * FROM items RIGHT OUTER JOIN b ON (b.items_id = items.id) FULL OUTER JOIN c ON (c.b_id = b.id)'
|
1221
|
+
'SELECT * FROM "items" RIGHT OUTER JOIN "b" ON ("b"."items_id" = "items"."id") FULL OUTER JOIN "c" ON ("c"."b_id" = "b"."id")'
|
1153
1222
|
end
|
1154
1223
|
|
1155
1224
|
specify "should support left outer joins" do
|
1156
1225
|
@d.join_table(:left_outer, :categories, :category_id).sql.should ==
|
1157
|
-
'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.category_id = items.id)'
|
1226
|
+
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1158
1227
|
|
1159
1228
|
@d.left_outer_join(:categories, :category_id).sql.should ==
|
1160
|
-
'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.category_id = items.id)'
|
1229
|
+
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1161
1230
|
end
|
1162
1231
|
|
1163
1232
|
specify "should support right outer joins" do
|
1164
1233
|
@d.join_table(:right_outer, :categories, :category_id).sql.should ==
|
1165
|
-
'SELECT * FROM items RIGHT OUTER JOIN categories ON (categories.category_id = items.id)'
|
1234
|
+
'SELECT * FROM "items" RIGHT OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1166
1235
|
|
1167
1236
|
@d.right_outer_join(:categories, :category_id).sql.should ==
|
1168
|
-
'SELECT * FROM items RIGHT OUTER JOIN categories ON (categories.category_id = items.id)'
|
1237
|
+
'SELECT * FROM "items" RIGHT OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1169
1238
|
end
|
1170
1239
|
|
1171
1240
|
specify "should support full outer joins" do
|
1172
1241
|
@d.join_table(:full_outer, :categories, :category_id).sql.should ==
|
1173
|
-
'SELECT * FROM items FULL OUTER JOIN categories ON (categories.category_id = items.id)'
|
1242
|
+
'SELECT * FROM "items" FULL OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1174
1243
|
|
1175
1244
|
@d.full_outer_join(:categories, :category_id).sql.should ==
|
1176
|
-
'SELECT * FROM items FULL OUTER JOIN categories ON (categories.category_id = items.id)'
|
1245
|
+
'SELECT * FROM "items" FULL OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1177
1246
|
end
|
1178
1247
|
|
1179
1248
|
specify "should support inner joins" do
|
1180
1249
|
@d.join_table(:inner, :categories, :category_id).sql.should ==
|
1181
|
-
'SELECT * FROM items INNER JOIN categories ON (categories.category_id = items.id)'
|
1250
|
+
'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1182
1251
|
|
1183
1252
|
@d.inner_join(:categories, :category_id).sql.should ==
|
1184
|
-
'SELECT * FROM items INNER JOIN categories ON (categories.category_id = items.id)'
|
1253
|
+
'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1185
1254
|
end
|
1186
1255
|
|
1187
1256
|
specify "should default to an inner join" do
|
1188
1257
|
@d.join_table(nil, :categories, :category_id).sql.should ==
|
1189
|
-
'SELECT * FROM items INNER JOIN categories ON (categories.category_id = items.id)'
|
1258
|
+
'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1190
1259
|
|
1191
1260
|
@d.join(:categories, :category_id).sql.should ==
|
1192
|
-
'SELECT * FROM items INNER JOIN categories ON (categories.category_id = items.id)'
|
1261
|
+
'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1193
1262
|
end
|
1194
1263
|
|
1195
1264
|
specify "should raise if an invalid join type is specified" do
|
@@ -1197,27 +1266,28 @@ context "Dataset#join_table" do
|
|
1197
1266
|
end
|
1198
1267
|
|
1199
1268
|
specify "should support aliased tables" do
|
1200
|
-
@d.from('stats
|
1201
|
-
'SELECT * FROM stats
|
1269
|
+
@d.from('stats').join('players', {:id => :player_id}, 'p').sql.should ==
|
1270
|
+
'SELECT * FROM "stats" INNER JOIN "players" "p" ON ("p"."id" = "stats"."player_id")'
|
1202
1271
|
|
1203
|
-
ds = Sequel::Dataset.new(nil).from(:foo => :f)
|
1204
|
-
|
1205
|
-
|
1272
|
+
ds = Sequel::Dataset.new(nil).from(:foo => :f)
|
1273
|
+
ds.quote_identifiers = true
|
1274
|
+
ds.join_table(:inner, :bar, :id => :bar_id).sql.should ==
|
1275
|
+
'SELECT * FROM "foo" "f" INNER JOIN "bar" ON ("bar"."id" = "f"."bar_id")'
|
1206
1276
|
end
|
1207
1277
|
|
1208
1278
|
specify "should allow for arbitrary conditions in the JOIN clause" do
|
1209
1279
|
@d.join_table(:left_outer, :categories, :status => 0).sql.should ==
|
1210
|
-
'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.status = 0)'
|
1280
|
+
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."status" = 0)'
|
1211
1281
|
@d.join_table(:left_outer, :categories, :categorizable_type => "Post").sql.should ==
|
1212
|
-
|
1282
|
+
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."categorizable_type" = \'Post\')'
|
1213
1283
|
@d.join_table(:left_outer, :categories, :timestamp => "CURRENT_TIMESTAMP".lit).sql.should ==
|
1214
|
-
|
1284
|
+
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."timestamp" = CURRENT_TIMESTAMP)'
|
1215
1285
|
@d.join_table(:left_outer, :categories, :status => [1, 2, 3]).sql.should ==
|
1216
|
-
|
1286
|
+
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."status" IN (1, 2, 3))'
|
1217
1287
|
end
|
1218
1288
|
|
1219
1289
|
specify "should raise error for a table without a source" do
|
1220
|
-
proc {Sequel::Dataset.new(nil).join('players
|
1290
|
+
proc {Sequel::Dataset.new(nil).join('players', :id => :player_id)}. \
|
1221
1291
|
should raise_error(Sequel::Error)
|
1222
1292
|
end
|
1223
1293
|
|
@@ -1225,12 +1295,12 @@ context "Dataset#join_table" do
|
|
1225
1295
|
ds = Sequel::Dataset.new(nil).from(:categories)
|
1226
1296
|
|
1227
1297
|
@d.join_table(:left_outer, ds, :item_id => :id).sql.should ==
|
1228
|
-
'SELECT * FROM items LEFT OUTER JOIN (SELECT * FROM categories) t1 ON (t1.item_id = items.id)'
|
1298
|
+
'SELECT * FROM "items" LEFT OUTER JOIN (SELECT * FROM categories) "t1" ON ("t1"."item_id" = "items"."id")'
|
1229
1299
|
|
1230
1300
|
ds.filter!(:active => true)
|
1231
1301
|
|
1232
1302
|
@d.join_table(:left_outer, ds, :item_id => :id).sql.should ==
|
1233
|
-
'SELECT * FROM items LEFT OUTER JOIN (SELECT * FROM categories WHERE (active = \'t\')) t1 ON (t1.item_id = items.id)'
|
1303
|
+
'SELECT * FROM "items" LEFT OUTER JOIN (SELECT * FROM categories WHERE (active = \'t\')) "t1" ON ("t1"."item_id" = "items"."id")'
|
1234
1304
|
end
|
1235
1305
|
|
1236
1306
|
specify "should support joining multiple datasets" do
|
@@ -1239,9 +1309,9 @@ context "Dataset#join_table" do
|
|
1239
1309
|
ds3 = Sequel::Dataset.new(nil).from(:attributes).filter("name = 'blah'")
|
1240
1310
|
|
1241
1311
|
@d.join_table(:left_outer, ds, :item_id => :id).join_table(:inner, ds2, :node_id=>:id).join_table(:right_outer, ds3, :attribute_id=>:id).sql.should ==
|
1242
|
-
'SELECT * FROM items LEFT OUTER JOIN (SELECT * FROM categories) t1 ON (t1.item_id = items.id) ' \
|
1243
|
-
'INNER JOIN (SELECT name FROM nodes) t2 ON (t2.node_id = t1.id) ' \
|
1244
|
-
|
1312
|
+
'SELECT * FROM "items" LEFT OUTER JOIN (SELECT * FROM categories) "t1" ON ("t1"."item_id" = "items"."id") ' \
|
1313
|
+
'INNER JOIN (SELECT name FROM nodes) "t2" ON ("t2"."node_id" = "t1"."id") ' \
|
1314
|
+
'RIGHT OUTER JOIN (SELECT * FROM attributes WHERE (name = \'blah\')) "t3" ON ("t3"."attribute_id" = "t2"."id")'
|
1245
1315
|
end
|
1246
1316
|
|
1247
1317
|
specify "should support joining objects that respond to :table_name" do
|
@@ -1249,7 +1319,7 @@ context "Dataset#join_table" do
|
|
1249
1319
|
def ds.table_name; :categories end
|
1250
1320
|
|
1251
1321
|
@d.join(ds, :item_id => :id).sql.should ==
|
1252
|
-
'SELECT * FROM items INNER JOIN categories ON (categories.item_id = items.id)'
|
1322
|
+
'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."item_id" = "items"."id")'
|
1253
1323
|
end
|
1254
1324
|
end
|
1255
1325
|
|
@@ -1292,11 +1362,13 @@ context "Dataset#set" do
|
|
1292
1362
|
specify "should act as alias to #update" do
|
1293
1363
|
@d.set({:x => 3})
|
1294
1364
|
@d.last_sql.should == 'UPDATE items SET x = 3'
|
1365
|
+
end
|
1295
1366
|
|
1296
|
-
|
1367
|
+
pt_specify "should accept a block" do
|
1368
|
+
@d.set{:x << :x + 1}
|
1297
1369
|
@d.last_sql.should == 'UPDATE items SET x = (x + 1)'
|
1298
1370
|
|
1299
|
-
@d.set
|
1371
|
+
@d.set{(:x|1) << (:x|2) + 1}
|
1300
1372
|
@d.last_sql.should == 'UPDATE items SET x[1] = (x[2] + 1)'
|
1301
1373
|
end
|
1302
1374
|
end
|
@@ -1338,23 +1410,23 @@ context "Dataset aggregate methods" do
|
|
1338
1410
|
end
|
1339
1411
|
|
1340
1412
|
specify "should include min" do
|
1341
|
-
@d.min(:a).should == 'SELECT min(a)
|
1413
|
+
@d.min(:a).should == 'SELECT min(a) FROM test LIMIT 1'
|
1342
1414
|
end
|
1343
1415
|
|
1344
1416
|
specify "should include max" do
|
1345
|
-
@d.max(:b).should == 'SELECT max(b)
|
1417
|
+
@d.max(:b).should == 'SELECT max(b) FROM test LIMIT 1'
|
1346
1418
|
end
|
1347
1419
|
|
1348
1420
|
specify "should include sum" do
|
1349
|
-
@d.sum(:c).should == 'SELECT sum(c)
|
1421
|
+
@d.sum(:c).should == 'SELECT sum(c) FROM test LIMIT 1'
|
1350
1422
|
end
|
1351
1423
|
|
1352
1424
|
specify "should include avg" do
|
1353
|
-
@d.avg(:d).should == 'SELECT avg(d)
|
1425
|
+
@d.avg(:d).should == 'SELECT avg(d) FROM test LIMIT 1'
|
1354
1426
|
end
|
1355
1427
|
|
1356
1428
|
specify "should accept qualified columns" do
|
1357
|
-
@d.avg(:test__bc).should == 'SELECT avg(test.bc)
|
1429
|
+
@d.avg(:test__bc).should == 'SELECT avg(test.bc) FROM test LIMIT 1'
|
1358
1430
|
end
|
1359
1431
|
end
|
1360
1432
|
|
@@ -1377,17 +1449,16 @@ context "Dataset#range" do
|
|
1377
1449
|
@d.range(:stamp)
|
1378
1450
|
@d.last_sql.should == "SELECT min(stamp) AS v1, max(stamp) AS v2 FROM test LIMIT 1"
|
1379
1451
|
|
1380
|
-
@d.filter
|
1452
|
+
@d.filter(:price > 100).range(:stamp)
|
1381
1453
|
@d.last_sql.should == "SELECT min(stamp) AS v1, max(stamp) AS v2 FROM test WHERE (price > 100) LIMIT 1"
|
1382
1454
|
end
|
1383
1455
|
|
1384
1456
|
specify "should return a range object" do
|
1385
1457
|
@d.range(:tryme).should == (1..10)
|
1386
|
-
@d.last_sql.should == "SELECT min(tryme) AS v1, max(tryme) AS v2 FROM test LIMIT 1"
|
1387
1458
|
end
|
1388
1459
|
end
|
1389
1460
|
|
1390
|
-
context "Dataset#
|
1461
|
+
context "Dataset#interval" do
|
1391
1462
|
setup do
|
1392
1463
|
c = Class.new(Sequel::Dataset) do
|
1393
1464
|
@@sql = nil
|
@@ -1404,147 +1475,77 @@ context "Dataset#range" do
|
|
1404
1475
|
|
1405
1476
|
specify "should generate a correct SQL statement" do
|
1406
1477
|
@d.interval(:stamp)
|
1407
|
-
@d.last_sql.should == "SELECT (max(stamp) - min(stamp))
|
1478
|
+
@d.last_sql.should == "SELECT (max(stamp) - min(stamp)) FROM test LIMIT 1"
|
1408
1479
|
|
1409
|
-
@d.filter
|
1410
|
-
@d.last_sql.should == "SELECT (max(stamp) - min(stamp))
|
1480
|
+
@d.filter(:price > 100).interval(:stamp)
|
1481
|
+
@d.last_sql.should == "SELECT (max(stamp) - min(stamp)) FROM test WHERE (price > 100) LIMIT 1"
|
1411
1482
|
end
|
1412
1483
|
|
1413
|
-
specify "should return
|
1484
|
+
specify "should return an integer" do
|
1414
1485
|
@d.interval(:tryme).should == 1234
|
1415
|
-
@d.last_sql.should == "SELECT (max(tryme) - min(tryme)) AS v FROM test LIMIT 1"
|
1416
1486
|
end
|
1417
1487
|
end
|
1418
1488
|
|
1419
|
-
context "Dataset#first" do
|
1489
|
+
context "Dataset #first and #last" do
|
1420
1490
|
setup do
|
1421
1491
|
@c = Class.new(Sequel::Dataset) do
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
@@last_dataset
|
1427
|
-
end
|
1428
|
-
|
1429
|
-
def self.last_opts
|
1430
|
-
@@last_opts
|
1431
|
-
end
|
1432
|
-
|
1433
|
-
def single_record(opts = nil)
|
1434
|
-
@@last_opts = @opts.merge(opts || {})
|
1435
|
-
{:a => 1, :b => 2}
|
1436
|
-
end
|
1437
|
-
|
1438
|
-
def all
|
1439
|
-
@@last_dataset = self
|
1440
|
-
[{:a => 1, :b => 2}] * @opts[:limit]
|
1492
|
+
def each(opts = nil, &block)
|
1493
|
+
s = select_sql(opts)
|
1494
|
+
x = [:a,1,:b,2,s]
|
1495
|
+
i = /LIMIT (\d+)/.match(s)[1].to_i.times{yield x}
|
1441
1496
|
end
|
1442
1497
|
end
|
1443
1498
|
@d = @c.new(nil).from(:test)
|
1444
1499
|
end
|
1445
1500
|
|
1446
|
-
specify "should return
|
1447
|
-
@d.
|
1448
|
-
@
|
1501
|
+
specify "should return a single record if no argument is given" do
|
1502
|
+
@d.order(:a).first.should == [:a,1,:b,2, 'SELECT * FROM test ORDER BY a LIMIT 1']
|
1503
|
+
@d.order(:a).last.should == [:a,1,:b,2, 'SELECT * FROM test ORDER BY a DESC LIMIT 1']
|
1504
|
+
end
|
1449
1505
|
|
1450
|
-
|
1451
|
-
@
|
1506
|
+
specify "should return the first/last matching record if argument is not an Integer" do
|
1507
|
+
@d.order(:a).first(:z => 26).should == [:a,1,:b,2, 'SELECT * FROM test WHERE (z = 26) ORDER BY a LIMIT 1']
|
1508
|
+
@d.order(:a).first('z = ?', 15).should == [:a,1,:b,2, 'SELECT * FROM test WHERE (z = 15) ORDER BY a LIMIT 1']
|
1509
|
+
@d.order(:a).last(:z => 26).should == [:a,1,:b,2, 'SELECT * FROM test WHERE (z = 26) ORDER BY a DESC LIMIT 1']
|
1510
|
+
@d.order(:a).last('z = ?', 15).should == [:a,1,:b,2, 'SELECT * FROM test WHERE (z = 15) ORDER BY a DESC LIMIT 1']
|
1452
1511
|
end
|
1453
1512
|
|
1454
|
-
specify "should
|
1455
|
-
|
1456
|
-
@
|
1513
|
+
specify "should set the limit and return an array of records if the given number is > 1" do
|
1514
|
+
i = rand(10) + 10
|
1515
|
+
r = @d.order(:a).first(i).should == [[:a,1,:b,2, "SELECT * FROM test ORDER BY a LIMIT #{i}"]] * i
|
1516
|
+
i = rand(10) + 10
|
1517
|
+
r = @d.order(:a).last(i).should == [[:a,1,:b,2, "SELECT * FROM test ORDER BY a DESC LIMIT #{i}"]] * i
|
1457
1518
|
end
|
1458
1519
|
|
1459
|
-
|
1460
|
-
@d.first.should ==
|
1520
|
+
pt_specify "should return the first matching record if a block is given without an argument" do
|
1521
|
+
@d.first{:z > 26}.should == [:a,1,:b,2, 'SELECT * FROM test WHERE (z > 26) LIMIT 1']
|
1522
|
+
@d.order(:name).last{:z > 26}.should == [:a,1,:b,2, 'SELECT * FROM test WHERE (z > 26) ORDER BY name DESC LIMIT 1']
|
1461
1523
|
end
|
1462
1524
|
|
1463
|
-
|
1464
|
-
@d.first
|
1465
|
-
@
|
1466
|
-
|
1467
|
-
i = rand(10) + 10
|
1468
|
-
@d.first(i)
|
1469
|
-
@c.last_dataset.opts[:limit].should == i
|
1525
|
+
pt_specify "should combine block and standard argument filters if argument is not an Integer" do
|
1526
|
+
@d.first(:y=>25){:z > 26}.should == [:a,1,:b,2, 'SELECT * FROM test WHERE ((z > 26) AND (y = 25)) LIMIT 1']
|
1527
|
+
@d.order(:name).last('y = ?', 16){:z > 26}.should == [:a,1,:b,2, 'SELECT * FROM test WHERE ((z > 26) AND (y = 16)) ORDER BY name DESC LIMIT 1']
|
1470
1528
|
end
|
1471
1529
|
|
1472
|
-
|
1530
|
+
pt_specify "should filter and return an array of records if an Integer argument is provided and a block is given" do
|
1473
1531
|
i = rand(10) + 10
|
1474
|
-
r = @d.first(i)
|
1475
|
-
|
1476
|
-
r.
|
1477
|
-
r.each {|row| row.should == {:a => 1, :b => 2}}
|
1478
|
-
end
|
1479
|
-
end
|
1480
|
-
|
1481
|
-
context "Dataset#last" do
|
1482
|
-
setup do
|
1483
|
-
@c = Class.new(Sequel::Dataset) do
|
1484
|
-
@@last_dataset = nil
|
1485
|
-
|
1486
|
-
def self.last_dataset
|
1487
|
-
@@last_dataset
|
1488
|
-
end
|
1489
|
-
|
1490
|
-
def single_record(opts = nil)
|
1491
|
-
@@last_dataset = clone(opts) if opts
|
1492
|
-
{:a => 1, :b => 2}
|
1493
|
-
end
|
1494
|
-
|
1495
|
-
def all
|
1496
|
-
@@last_dataset = self
|
1497
|
-
[{:a => 1, :b => 2}] * @opts[:limit]
|
1498
|
-
end
|
1499
|
-
end
|
1500
|
-
@d = @c.new(nil).from(:test)
|
1532
|
+
r = @d.order(:a).first(i){:z > 26}.should == [[:a,1,:b,2, "SELECT * FROM test WHERE (z > 26) ORDER BY a LIMIT #{i}"]] * i
|
1533
|
+
i = rand(10) + 10
|
1534
|
+
r = @d.order(:a).last(i){:z > 26}.should == [[:a,1,:b,2, "SELECT * FROM test WHERE (z > 26) ORDER BY a DESC LIMIT #{i}"]] * i
|
1501
1535
|
end
|
1502
1536
|
|
1503
|
-
specify "should raise if no order is given" do
|
1537
|
+
specify "#last should raise if no order is given" do
|
1504
1538
|
proc {@d.last}.should raise_error(Sequel::Error)
|
1505
1539
|
proc {@d.last(2)}.should raise_error(Sequel::Error)
|
1506
1540
|
proc {@d.order(:a).last}.should_not raise_error
|
1507
1541
|
proc {@d.order(:a).last(2)}.should_not raise_error
|
1508
1542
|
end
|
1509
1543
|
|
1510
|
-
specify "should invert the order" do
|
1511
|
-
@d.order(:a).last
|
1512
|
-
@d.
|
1513
|
-
|
1514
|
-
@d.order(:
|
1515
|
-
@d.literal(@c.last_dataset.opts[:order]).should == @d.literal(:b)
|
1516
|
-
|
1517
|
-
@d.order(:c, :d).last
|
1518
|
-
@d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:c.desc, :d.desc])
|
1519
|
-
|
1520
|
-
@d.order(:e.desc, :f).last
|
1521
|
-
@d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:e, :f.desc])
|
1522
|
-
end
|
1523
|
-
|
1524
|
-
specify "should return the first matching record if a hash is specified" do
|
1525
|
-
@d.order(:a).last(:z => 26).should == {:a => 1, :b => 2}
|
1526
|
-
@c.last_dataset.opts[:where].should == ('(z = 26)')
|
1527
|
-
|
1528
|
-
@d.order(:a).last('z = ?', 15)
|
1529
|
-
@c.last_dataset.opts[:where].should == ('z = 15')
|
1530
|
-
end
|
1531
|
-
|
1532
|
-
specify "should return a single record if no argument is given" do
|
1533
|
-
@d.order(:a).last.should == {:a => 1, :b => 2}
|
1534
|
-
end
|
1535
|
-
|
1536
|
-
specify "should set the limit according to the given number" do
|
1537
|
-
i = rand(10) + 10
|
1538
|
-
r = @d.order(:a).last(i)
|
1539
|
-
@c.last_dataset.opts[:limit].should == i
|
1540
|
-
end
|
1541
|
-
|
1542
|
-
specify "should return an array with the records if argument is greater than 1" do
|
1543
|
-
i = rand(10) + 10
|
1544
|
-
r = @d.order(:a).last(i)
|
1545
|
-
r.should be_a_kind_of(Array)
|
1546
|
-
r.size.should == i
|
1547
|
-
r.each {|row| row.should == {:a => 1, :b => 2}}
|
1544
|
+
specify "#last should invert the order" do
|
1545
|
+
@d.order(:a).last.pop.should == 'SELECT * FROM test ORDER BY a DESC LIMIT 1'
|
1546
|
+
@d.order(:b.desc).last.pop.should == 'SELECT * FROM test ORDER BY b LIMIT 1'
|
1547
|
+
@d.order(:c, :d).last.pop.should == 'SELECT * FROM test ORDER BY c DESC, d DESC LIMIT 1'
|
1548
|
+
@d.order(:e.desc, :f).last.pop.should == 'SELECT * FROM test ORDER BY e, f DESC LIMIT 1'
|
1548
1549
|
end
|
1549
1550
|
end
|
1550
1551
|
|
@@ -1595,10 +1596,10 @@ context "Dataset#[]" do
|
|
1595
1596
|
|
1596
1597
|
specify "should return a single record filtered according to the given conditions" do
|
1597
1598
|
@d[:name => 'didi'].should == {1 => 2, 3 => 4}
|
1598
|
-
@c.last_dataset.opts[:where].should == "(name = 'didi')"
|
1599
|
+
@c.last_dataset.literal(@c.last_dataset.opts[:where]).should == "(name = 'didi')"
|
1599
1600
|
|
1600
1601
|
@d[:id => 5..45].should == {1 => 2, 3 => 4}
|
1601
|
-
@c.last_dataset.opts[:where].should == "(id >= 5 AND id <= 45)"
|
1602
|
+
@c.last_dataset.literal(@c.last_dataset.opts[:where]).should == "((id >= 5) AND (id <= 45))"
|
1602
1603
|
end
|
1603
1604
|
end
|
1604
1605
|
|
@@ -1617,14 +1618,18 @@ context "Dataset#single_record" do
|
|
1617
1618
|
@e = @cc.new(nil).from(:test)
|
1618
1619
|
end
|
1619
1620
|
|
1620
|
-
specify "should call each and return the
|
1621
|
-
@d.single_record.should == 'SELECT * FROM test'
|
1621
|
+
specify "should call each with a limit of 1 and return the record" do
|
1622
|
+
@d.single_record.should == 'SELECT * FROM test LIMIT 1'
|
1622
1623
|
end
|
1623
1624
|
|
1624
1625
|
specify "should pass opts to each" do
|
1625
|
-
@d.single_record(:
|
1626
|
+
@d.single_record(:order => [:name]).should == 'SELECT * FROM test ORDER BY name LIMIT 1'
|
1626
1627
|
end
|
1627
1628
|
|
1629
|
+
specify "should override the limit if passed as an option" do
|
1630
|
+
@d.single_record(:limit => 3).should == 'SELECT * FROM test LIMIT 1'
|
1631
|
+
end
|
1632
|
+
|
1628
1633
|
specify "should return nil if no record is present" do
|
1629
1634
|
@e.single_record.should be_nil
|
1630
1635
|
end
|
@@ -1646,14 +1651,14 @@ context "Dataset#single_value" do
|
|
1646
1651
|
end
|
1647
1652
|
|
1648
1653
|
specify "should call each and return the first value of the first record" do
|
1649
|
-
@d.single_value.should == 'SELECT * FROM test'
|
1654
|
+
@d.single_value.should == 'SELECT * FROM test LIMIT 1'
|
1650
1655
|
end
|
1651
1656
|
|
1652
1657
|
specify "should pass opts to each" do
|
1653
|
-
@d.single_value(:
|
1658
|
+
@d.single_value(:from => [:blah]).should == 'SELECT * FROM blah LIMIT 1'
|
1654
1659
|
end
|
1655
1660
|
|
1656
|
-
specify "should return nil" do
|
1661
|
+
specify "should return nil if no records" do
|
1657
1662
|
@e.single_value.should be_nil
|
1658
1663
|
end
|
1659
1664
|
end
|
@@ -1673,16 +1678,16 @@ context "Dataset#get" do
|
|
1673
1678
|
end
|
1674
1679
|
|
1675
1680
|
specify "should select the specified column and fetch its value" do
|
1676
|
-
@d.get(:name).should == "SELECT name FROM test"
|
1677
|
-
@d.get(:abc).should == "SELECT abc FROM test" # the first available value is returned always
|
1681
|
+
@d.get(:name).should == "SELECT name FROM test LIMIT 1"
|
1682
|
+
@d.get(:abc).should == "SELECT abc FROM test LIMIT 1" # the first available value is returned always
|
1678
1683
|
end
|
1679
1684
|
|
1680
1685
|
specify "should work with filters" do
|
1681
|
-
@d.filter(:id => 1).get(:name).should == "SELECT name FROM test WHERE (id = 1)"
|
1686
|
+
@d.filter(:id => 1).get(:name).should == "SELECT name FROM test WHERE (id = 1) LIMIT 1"
|
1682
1687
|
end
|
1683
1688
|
|
1684
1689
|
specify "should work with aliased fields" do
|
1685
|
-
@d.get(:x__b.as(:name)).should == "SELECT x.b AS name FROM test"
|
1690
|
+
@d.get(:x__b.as(:name)).should == "SELECT x.b AS name FROM test LIMIT 1"
|
1686
1691
|
end
|
1687
1692
|
end
|
1688
1693
|
|
@@ -1749,12 +1754,6 @@ context "Dataset#set_model" do
|
|
1749
1754
|
@dataset.first.should == @m.new({:kind => 1})
|
1750
1755
|
end
|
1751
1756
|
|
1752
|
-
specify "should extend the dataset with a #destroy method" do
|
1753
|
-
@dataset.should_not respond_to(:destroy)
|
1754
|
-
@dataset.set_model(@m)
|
1755
|
-
@dataset.should respond_to(:destroy)
|
1756
|
-
end
|
1757
|
-
|
1758
1757
|
specify "should set opts[:naked] to nil" do
|
1759
1758
|
@dataset.opts[:naked] = true
|
1760
1759
|
@dataset.set_model(@m)
|
@@ -1964,58 +1963,10 @@ context "A dataset with associated model class(es)" do
|
|
1964
1963
|
end
|
1965
1964
|
end
|
1966
1965
|
|
1967
|
-
context "Dataset#destroy" do
|
1968
|
-
setup do
|
1969
|
-
db = Object.new
|
1970
|
-
m = Module.new do
|
1971
|
-
def transaction; yield; end
|
1972
|
-
end
|
1973
|
-
db.extend(m)
|
1974
|
-
|
1975
|
-
$DESTROYED = []
|
1976
|
-
|
1977
|
-
@m = Class.new do
|
1978
|
-
def initialize(c)
|
1979
|
-
@c = c
|
1980
|
-
end
|
1981
|
-
|
1982
|
-
attr_accessor :c
|
1983
|
-
|
1984
|
-
def ==(o)
|
1985
|
-
@c == o.c
|
1986
|
-
end
|
1987
|
-
|
1988
|
-
def destroy
|
1989
|
-
$DESTROYED << self
|
1990
|
-
end
|
1991
|
-
end
|
1992
|
-
$MODELS = [@m.new(12), @m.new(13)]
|
1993
|
-
|
1994
|
-
c = Class.new(Sequel::Dataset) do
|
1995
|
-
def fetch_rows(sql, &block)
|
1996
|
-
(12..13).each(&block)
|
1997
|
-
end
|
1998
|
-
end
|
1999
|
-
|
2000
|
-
@d = c.new(db).from(:test)
|
2001
|
-
@d.set_model(@m)
|
2002
|
-
end
|
2003
|
-
|
2004
|
-
specify "should call destroy for every model instance in the dataset" do
|
2005
|
-
count = @d.destroy
|
2006
|
-
count.should == 2
|
2007
|
-
$DESTROYED.should == $MODELS
|
2008
|
-
end
|
2009
|
-
|
2010
|
-
specify "should raise error if no models are associated with the dataset" do
|
2011
|
-
proc {@d.naked.destroy}.should raise_error(Sequel::Error)
|
2012
|
-
end
|
2013
|
-
end
|
2014
|
-
|
2015
1966
|
context "Dataset#<<" do
|
2016
1967
|
setup do
|
2017
1968
|
@d = Sequel::Dataset.new(nil)
|
2018
|
-
@d.meta_def(:insert) do
|
1969
|
+
@d.meta_def(:insert) do |*args|
|
2019
1970
|
1234567890
|
2020
1971
|
end
|
2021
1972
|
end
|
@@ -2080,7 +2031,20 @@ context "A paginated dataset" do
|
|
2080
2031
|
@d.paginate(4, 50).current_page_record_count.should == 3
|
2081
2032
|
@d.paginate(5, 50).current_page_record_count.should == 0
|
2082
2033
|
end
|
2083
|
-
|
2034
|
+
|
2035
|
+
specify "should know if current page is last page" do
|
2036
|
+
@paginated.last_page?.should be_false
|
2037
|
+
@d.paginate(2, 20).last_page?.should be_false
|
2038
|
+
@d.paginate(5, 30).last_page?.should be_false
|
2039
|
+
@d.paginate(6, 30).last_page?.should be_true
|
2040
|
+
end
|
2041
|
+
|
2042
|
+
specify "should know if current page is first page" do
|
2043
|
+
@paginated.first_page?.should be_true
|
2044
|
+
@d.paginate(1, 20).first_page?.should be_true
|
2045
|
+
@d.paginate(2, 20).first_page?.should be_false
|
2046
|
+
end
|
2047
|
+
|
2084
2048
|
specify "should work with fixed sql" do
|
2085
2049
|
ds = @d.clone(:sql => 'select * from blah')
|
2086
2050
|
ds.meta_def(:count) {150}
|
@@ -2114,34 +2078,35 @@ context "Dataset#columns" do
|
|
2114
2078
|
setup do
|
2115
2079
|
@dataset = DummyDataset.new(nil).from(:items)
|
2116
2080
|
@dataset.meta_def(:columns=) {|c| @columns = c}
|
2117
|
-
|
2081
|
+
i = 'a'
|
2082
|
+
@dataset.meta_def(:each) {|o| @columns = select_sql(o||@opts) + i; i = i.next}
|
2118
2083
|
end
|
2119
2084
|
|
2120
|
-
specify "should return the value of @columns" do
|
2085
|
+
specify "should return the value of @columns if @columns is not nil" do
|
2121
2086
|
@dataset.columns = [:a, :b, :c]
|
2122
2087
|
@dataset.columns.should == [:a, :b, :c]
|
2123
2088
|
end
|
2124
2089
|
|
2125
|
-
specify "should
|
2090
|
+
specify "should attempt to get a single record and return @columns if @columns is nil" do
|
2126
2091
|
@dataset.columns = nil
|
2127
|
-
@dataset.columns.should == 'SELECT * FROM items'
|
2092
|
+
@dataset.columns.should == 'SELECT * FROM items LIMIT 1a'
|
2128
2093
|
@dataset.opts[:from] = [:nana]
|
2129
|
-
@dataset.columns.should == 'SELECT * FROM items'
|
2094
|
+
@dataset.columns.should == 'SELECT * FROM items LIMIT 1a'
|
2130
2095
|
end
|
2131
2096
|
end
|
2132
2097
|
|
2133
2098
|
context "Dataset#columns!" do
|
2134
2099
|
setup do
|
2135
2100
|
@dataset = DummyDataset.new(nil).from(:items)
|
2136
|
-
|
2137
|
-
@dataset.meta_def(:
|
2101
|
+
i = 'a'
|
2102
|
+
@dataset.meta_def(:each) {|o| @columns = select_sql(o||@opts) + i; i = i.next}
|
2138
2103
|
end
|
2139
2104
|
|
2140
|
-
specify "should always
|
2141
|
-
@dataset.columns
|
2142
|
-
@dataset.columns!.should == 'SELECT * FROM items'
|
2105
|
+
specify "should always attempt to get a record and return @columns" do
|
2106
|
+
@dataset.columns!.should == 'SELECT * FROM items LIMIT 1a'
|
2107
|
+
@dataset.columns!.should == 'SELECT * FROM items LIMIT 1b'
|
2143
2108
|
@dataset.opts[:from] = [:nana]
|
2144
|
-
@dataset.columns!.should == 'SELECT * FROM nana'
|
2109
|
+
@dataset.columns!.should == 'SELECT * FROM nana LIMIT 1c'
|
2145
2110
|
end
|
2146
2111
|
end
|
2147
2112
|
|
@@ -2336,13 +2301,13 @@ context "Dataset#query" do
|
|
2336
2301
|
specify "should support #where" do
|
2337
2302
|
q = @d.query do
|
2338
2303
|
from :zzz
|
2339
|
-
where
|
2304
|
+
where(:x + 2 > :y + 3)
|
2340
2305
|
end
|
2341
2306
|
q.class.should == @d.class
|
2342
2307
|
q.sql.should == "SELECT * FROM zzz WHERE ((x + 2) > (y + 3))"
|
2343
2308
|
|
2344
2309
|
q = @d.from(:zzz).query do
|
2345
|
-
where
|
2310
|
+
where((:x > 1) & (:y > 2))
|
2346
2311
|
end
|
2347
2312
|
q.class.should == @d.class
|
2348
2313
|
q.sql.should == "SELECT * FROM zzz WHERE ((x > 1) AND (y > 2))"
|
@@ -2358,7 +2323,7 @@ context "Dataset#query" do
|
|
2358
2323
|
q = @d.query do
|
2359
2324
|
from :abc
|
2360
2325
|
group_by :id
|
2361
|
-
having
|
2326
|
+
having(:x >= 2)
|
2362
2327
|
end
|
2363
2328
|
q.class.should == @d.class
|
2364
2329
|
q.sql.should == "SELECT * FROM abc GROUP BY id HAVING (x >= 2)"
|
@@ -2374,7 +2339,7 @@ context "Dataset#query" do
|
|
2374
2339
|
end
|
2375
2340
|
|
2376
2341
|
specify "should raise on non-chainable method calls" do
|
2377
|
-
proc {@d.query {
|
2342
|
+
proc {@d.query {first_source}}.should raise_error(Sequel::Error)
|
2378
2343
|
end
|
2379
2344
|
|
2380
2345
|
specify "should raise on each, insert, update, delete" do
|
@@ -2410,8 +2375,8 @@ context "Dataset" do
|
|
2410
2375
|
@d.sql.should == "SELECT * FROM x WHERE (y = 1)"
|
2411
2376
|
end
|
2412
2377
|
|
2413
|
-
|
2414
|
-
@d.filter!
|
2378
|
+
pt_specify "should support self-changing filter! with block" do
|
2379
|
+
@d.filter!{:y == 2}
|
2415
2380
|
@d.sql.should == "SELECT * FROM x WHERE (y = 2)"
|
2416
2381
|
end
|
2417
2382
|
|
@@ -2565,27 +2530,27 @@ context "Dataset#transform" do
|
|
2565
2530
|
specify "should support stock Marshal transformation with Base64 encoding" do
|
2566
2531
|
@ds.transform(:x => :marshal)
|
2567
2532
|
|
2568
|
-
@ds.raw = {:x =>
|
2533
|
+
@ds.raw = {:x => [Marshal.dump([1, 2, 3])].pack('m'), :y => 'hello'}
|
2569
2534
|
@ds.first.should == {:x => [1, 2, 3], :y => 'hello'}
|
2570
2535
|
|
2571
2536
|
@ds.insert(:x => :toast)
|
2572
|
-
@ds.sql.should == "INSERT INTO items (x) VALUES ('#{
|
2537
|
+
@ds.sql.should == "INSERT INTO items (x) VALUES ('#{[Marshal.dump(:toast)].pack('m')}')"
|
2573
2538
|
@ds.insert(:y => 'butter')
|
2574
2539
|
@ds.sql.should == "INSERT INTO items (y) VALUES ('butter')"
|
2575
2540
|
@ds.update(:x => ['dream'])
|
2576
|
-
@ds.sql.should == "UPDATE items SET x = '#{
|
2541
|
+
@ds.sql.should == "UPDATE items SET x = '#{[Marshal.dump(['dream'])].pack('m')}'"
|
2577
2542
|
|
2578
2543
|
@ds2 = @ds.filter(:a => 1)
|
2579
|
-
@ds2.raw = {:x =>
|
2544
|
+
@ds2.raw = {:x => [Marshal.dump([1, 2, 3])].pack('m'), :y => 'hello'}
|
2580
2545
|
@ds2.first.should == {:x => [1, 2, 3], :y => 'hello'}
|
2581
2546
|
@ds2.insert(:x => :toast)
|
2582
|
-
@ds2.sql.should == "INSERT INTO items (x) VALUES ('#{
|
2547
|
+
@ds2.sql.should == "INSERT INTO items (x) VALUES ('#{[Marshal.dump(:toast)].pack('m')}')"
|
2583
2548
|
|
2584
2549
|
@ds.row_proc = proc{|r| r[:z] = r[:x] * 2; r}
|
2585
|
-
@ds.raw = {:x =>
|
2550
|
+
@ds.raw = {:x => [Marshal.dump("wow")].pack('m'), :y => 'hello'}
|
2586
2551
|
@ds.first.should == {:x => "wow", :y => 'hello', :z => "wowwow"}
|
2587
2552
|
f = nil
|
2588
|
-
@ds.raw = {:x =>
|
2553
|
+
@ds.raw = {:x => [Marshal.dump("wow")].pack('m'), :y => 'hello'}
|
2589
2554
|
@ds.each(:naked => true) {|r| f = r}
|
2590
2555
|
f.should == {:x => "wow", :y => 'hello'}
|
2591
2556
|
end
|
@@ -2611,7 +2576,7 @@ context "A dataset with a transform" do
|
|
2611
2576
|
specify "should automatically transform hash filters" do
|
2612
2577
|
@ds.filter(:y => 2).sql.should == 'SELECT * FROM items WHERE (y = 2)'
|
2613
2578
|
|
2614
|
-
@ds.filter(:x => 2).sql.should == "SELECT * FROM items WHERE (x = '#{
|
2579
|
+
@ds.filter(:x => 2).sql.should == "SELECT * FROM items WHERE (x = '#{[Marshal.dump(2)].pack('m')}')"
|
2615
2580
|
end
|
2616
2581
|
end
|
2617
2582
|
|
@@ -2647,88 +2612,6 @@ context "Dataset#to_csv" do
|
|
2647
2612
|
end
|
2648
2613
|
end
|
2649
2614
|
|
2650
|
-
### DEPRECATED
|
2651
|
-
context "Dataset magic methods" do
|
2652
|
-
setup do
|
2653
|
-
@c = Class.new(Sequel::Dataset) do
|
2654
|
-
@@sqls = []
|
2655
|
-
|
2656
|
-
def self.sqls; @@sqls; end
|
2657
|
-
|
2658
|
-
def fetch_rows(sql)
|
2659
|
-
@@sqls << sql
|
2660
|
-
yield({:a => 1, :b => 2})
|
2661
|
-
end
|
2662
|
-
end
|
2663
|
-
|
2664
|
-
@ds = @c.new(nil).from(:items)
|
2665
|
-
end
|
2666
|
-
|
2667
|
-
specify "should support order_by_xxx" do
|
2668
|
-
@ds.should_not respond_to(:order_by_name)
|
2669
|
-
proc {@ds.order_by_name}.should_not raise_error
|
2670
|
-
@ds.should respond_to(:order_by_name)
|
2671
|
-
@ds.order_by_name.should be_a_kind_of(@c)
|
2672
|
-
@ds.order_by_name.sql.should == "SELECT * FROM items ORDER BY name"
|
2673
|
-
end
|
2674
|
-
|
2675
|
-
specify "should support group_by_xxx" do
|
2676
|
-
@ds.should_not respond_to(:group_by_name)
|
2677
|
-
proc {@ds.group_by_name}.should_not raise_error
|
2678
|
-
@ds.should respond_to(:group_by_name)
|
2679
|
-
@ds.group_by_name.should be_a_kind_of(@c)
|
2680
|
-
@ds.group_by_name.sql.should == "SELECT * FROM items GROUP BY name"
|
2681
|
-
end
|
2682
|
-
|
2683
|
-
specify "should support count_by_xxx" do
|
2684
|
-
@ds.should_not respond_to(:count_by_name)
|
2685
|
-
proc {@ds.count_by_name}.should_not raise_error
|
2686
|
-
@ds.should respond_to(:count_by_name)
|
2687
|
-
@ds.count_by_name.should be_a_kind_of(@c)
|
2688
|
-
@ds.count_by_name.sql.should == "SELECT name, count(*) AS count FROM items GROUP BY name ORDER BY count"
|
2689
|
-
end
|
2690
|
-
|
2691
|
-
specify "should support filter_by_xxx" do
|
2692
|
-
@ds.should_not respond_to(:filter_by_name)
|
2693
|
-
proc {@ds.filter_by_name('sharon')}.should_not raise_error
|
2694
|
-
@ds.should respond_to(:filter_by_name)
|
2695
|
-
@ds.filter_by_name('sharon').should be_a_kind_of(@c)
|
2696
|
-
@ds.filter_by_name('sharon').sql.should == "SELECT * FROM items WHERE (name = 'sharon')"
|
2697
|
-
end
|
2698
|
-
|
2699
|
-
specify "should support all_by_xxx" do
|
2700
|
-
@ds.should_not respond_to(:all_by_name)
|
2701
|
-
proc {@ds.all_by_name('sharon')}.should_not raise_error
|
2702
|
-
@ds.should respond_to(:all_by_name)
|
2703
|
-
@ds.all_by_name('sharon').should == [{:a => 1, :b => 2}]
|
2704
|
-
@c.sqls.should == ["SELECT * FROM items WHERE (name = 'sharon')"] * 2
|
2705
|
-
end
|
2706
|
-
|
2707
|
-
specify "should support find_by_xxx" do
|
2708
|
-
@ds.should_not respond_to(:find_by_name)
|
2709
|
-
proc {@ds.find_by_name('sharon')}.should_not raise_error
|
2710
|
-
@ds.should respond_to(:find_by_name)
|
2711
|
-
@ds.find_by_name('sharon').should == {:a => 1, :b => 2}
|
2712
|
-
@c.sqls.should == ["SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"] * 2
|
2713
|
-
end
|
2714
|
-
|
2715
|
-
specify "should support first_by_xxx" do
|
2716
|
-
@ds.should_not respond_to(:first_by_name)
|
2717
|
-
proc {@ds.first_by_name('sharon')}.should_not raise_error
|
2718
|
-
@ds.should respond_to(:first_by_name)
|
2719
|
-
@ds.first_by_name('sharon').should == {:a => 1, :b => 2}
|
2720
|
-
@c.sqls.should == ["SELECT * FROM items ORDER BY name LIMIT 1"] * 2
|
2721
|
-
end
|
2722
|
-
|
2723
|
-
specify "should support last_by_xxx" do
|
2724
|
-
@ds.should_not respond_to(:last_by_name)
|
2725
|
-
proc {@ds.last_by_name('sharon')}.should_not raise_error
|
2726
|
-
@ds.should respond_to(:last_by_name)
|
2727
|
-
@ds.last_by_name('sharon').should == {:a => 1, :b => 2}
|
2728
|
-
@c.sqls.should == ["SELECT * FROM items ORDER BY name DESC LIMIT 1"] * 2
|
2729
|
-
end
|
2730
|
-
end
|
2731
|
-
|
2732
2615
|
context "Dataset#create_view" do
|
2733
2616
|
setup do
|
2734
2617
|
@dbc = Class.new(Sequel::Database) do
|
@@ -2916,7 +2799,7 @@ context "Dataset#grep" do
|
|
2916
2799
|
|
2917
2800
|
specify "should format a SQL filter correctly" do
|
2918
2801
|
@ds.grep(:title, 'ruby').sql.should ==
|
2919
|
-
"SELECT * FROM posts WHERE (title LIKE 'ruby')"
|
2802
|
+
"SELECT * FROM posts WHERE ((title LIKE 'ruby'))"
|
2920
2803
|
end
|
2921
2804
|
|
2922
2805
|
specify "should support multiple columns" do
|
@@ -2926,30 +2809,19 @@ context "Dataset#grep" do
|
|
2926
2809
|
|
2927
2810
|
specify "should support multiple search terms" do
|
2928
2811
|
@ds.grep(:title, ['abc', 'def']).sql.should ==
|
2929
|
-
"SELECT * FROM posts WHERE ((title LIKE 'abc') OR (title LIKE 'def'))"
|
2812
|
+
"SELECT * FROM posts WHERE (((title LIKE 'abc') OR (title LIKE 'def')))"
|
2930
2813
|
end
|
2931
2814
|
|
2932
2815
|
specify "should support multiple columns and search terms" do
|
2933
2816
|
@ds.grep([:title, :body], ['abc', 'def']).sql.should ==
|
2934
|
-
"SELECT * FROM posts WHERE ((title LIKE 'abc') OR (title LIKE 'def') OR (body LIKE 'abc') OR (body LIKE 'def'))"
|
2935
|
-
end
|
2936
|
-
|
2937
|
-
specify "should support regexps
|
2938
|
-
@ds.meta_def(:match_expr) do |l, r|
|
2939
|
-
case r
|
2940
|
-
when String
|
2941
|
-
"(#{literal(l)} LIKE #{literal(r)})"
|
2942
|
-
when Regexp
|
2943
|
-
"(#{literal(l)} =~ #{literal(r.source)})"
|
2944
|
-
else
|
2945
|
-
raise Sequel::Error, "Unsupported match pattern class (#{r.class})."
|
2946
|
-
end
|
2947
|
-
end
|
2948
|
-
|
2817
|
+
"SELECT * FROM posts WHERE (((title LIKE 'abc') OR (title LIKE 'def')) OR ((body LIKE 'abc') OR (body LIKE 'def')))"
|
2818
|
+
end
|
2819
|
+
|
2820
|
+
specify "should support regexps though the database may not support it" do
|
2949
2821
|
@ds.grep(:title, /ruby/).sql.should ==
|
2950
|
-
"SELECT * FROM posts WHERE (title
|
2822
|
+
"SELECT * FROM posts WHERE ((title ~ 'ruby'))"
|
2951
2823
|
|
2952
2824
|
@ds.grep(:title, [/^ruby/, 'ruby']).sql.should ==
|
2953
|
-
"SELECT * FROM posts WHERE ((title
|
2825
|
+
"SELECT * FROM posts WHERE (((title ~ '^ruby') OR (title LIKE 'ruby')))"
|
2954
2826
|
end
|
2955
2827
|
end
|