sequel_core 1.5.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|