sequel_core 2.1.0 → 2.2.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 +39 -1
- data/Rakefile +1 -1
- data/doc/dataset_filtering.rdoc +5 -87
- data/lib/sequel_core.rb +20 -13
- data/lib/sequel_core/adapters/mysql.rb +12 -11
- data/lib/sequel_core/adapters/odbc_mssql.rb +3 -3
- data/lib/sequel_core/adapters/oracle.rb +2 -2
- data/lib/sequel_core/adapters/postgres.rb +46 -26
- data/lib/sequel_core/adapters/sqlite.rb +12 -0
- data/lib/sequel_core/core_sql.rb +7 -0
- data/lib/sequel_core/database.rb +12 -14
- data/lib/sequel_core/dataset.rb +6 -3
- data/lib/sequel_core/dataset/sql.rb +28 -25
- data/lib/sequel_core/object_graph.rb +23 -21
- data/lib/sequel_core/schema/sql.rb +5 -1
- data/lib/sequel_core/sql.rb +76 -5
- data/spec/adapters/mysql_spec.rb +33 -9
- data/spec/adapters/postgres_spec.rb +35 -3
- data/spec/adapters/sqlite_spec.rb +14 -2
- data/spec/core_sql_spec.rb +38 -3
- data/spec/database_spec.rb +19 -1
- data/spec/dataset_spec.rb +60 -66
- data/spec/{blockless_filters_spec.rb → expression_filters_spec.rb} +2 -10
- data/spec/object_graph_spec.rb +5 -0
- data/spec/schema_spec.rb +6 -6
- data/spec/spec_config.rb.example +2 -1
- data/spec/spec_helper.rb +0 -6
- metadata +3 -6
- data/lib/sequel_core/dataset/parse_tree_sequelizer.rb +0 -310
- data/lib/sequel_core/dataset/sequelizer.rb +0 -50
- data/spec/sequelizer_spec.rb +0 -504
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '../spec_helper.rb')
|
2
2
|
|
3
|
+
unless defined?(MYSQL_USER)
|
4
|
+
MYSQL_USER = 'root'
|
5
|
+
end
|
3
6
|
unless defined?(MYSQL_DB)
|
4
|
-
MYSQL_URL = (ENV['SEQUEL_MY_SPEC_DB']||
|
7
|
+
MYSQL_URL = (ENV['SEQUEL_MY_SPEC_DB']||"mysql://#{MYSQL_USER}@localhost/sandbox") unless defined? MYSQL_URL
|
5
8
|
MYSQL_DB = Sequel.connect(MYSQL_URL)
|
6
9
|
end
|
7
10
|
unless defined?(MYSQL_SOCKET_FILE)
|
@@ -36,6 +39,9 @@ context "A MySQL database" do
|
|
36
39
|
setup do
|
37
40
|
@db = MYSQL_DB
|
38
41
|
end
|
42
|
+
teardown do
|
43
|
+
Sequel.convert_tinyint_to_bool = true
|
44
|
+
end
|
39
45
|
|
40
46
|
specify "should provide disconnect functionality" do
|
41
47
|
@db.tables
|
@@ -66,6 +72,9 @@ context "A MySQL database" do
|
|
66
72
|
|
67
73
|
specify "should correctly parse the schema" do
|
68
74
|
@db.schema(:booltest, :reload=>true).should == [[:value, {:type=>:boolean, :allow_null=>true, :max_chars=>nil, :default=>nil, :db_type=>"tinyint", :numeric_precision=>3}]]
|
75
|
+
|
76
|
+
Sequel.convert_tinyint_to_bool = false
|
77
|
+
@db.schema(:booltest, :reload=>true).should == [[:value, {:type=>:integer, :allow_null=>true, :max_chars=>nil, :default=>nil, :db_type=>"tinyint", :numeric_precision=>3}]]
|
69
78
|
end
|
70
79
|
|
71
80
|
specify "should get the schema all database tables if no table name is used" do
|
@@ -248,6 +257,9 @@ context "MySQL datasets" do
|
|
248
257
|
setup do
|
249
258
|
@d = MYSQL_DB[:orders]
|
250
259
|
end
|
260
|
+
teardown do
|
261
|
+
Sequel.convert_tinyint_to_bool = true
|
262
|
+
end
|
251
263
|
|
252
264
|
specify "should correctly quote column references" do
|
253
265
|
@d.quote_identifiers = true
|
@@ -255,22 +267,34 @@ context "MySQL datasets" do
|
|
255
267
|
ack_stamp = Time.now - 15 * 60 # 15 minutes ago
|
256
268
|
@d.query do
|
257
269
|
select :market, :minute[:from_unixtime[:ack]].as(:minute)
|
258
|
-
where
|
259
|
-
:ack > ack_stamp
|
260
|
-
:market == market
|
261
|
-
end
|
270
|
+
where {(:ack > ack_stamp) & {:market => market}}
|
262
271
|
group_by :minute[:from_unixtime[:ack]]
|
263
272
|
end.sql.should == \
|
264
273
|
"SELECT `market`, minute(from_unixtime(`ack`)) AS `minute` FROM `orders` WHERE ((`ack` > #{@d.literal(ack_stamp)}) AND (`market` = 'ICE')) GROUP BY minute(from_unixtime(`ack`))"
|
265
274
|
end
|
266
275
|
|
267
|
-
specify "should accept and return tinyints as bools" do
|
276
|
+
specify "should accept and return tinyints as bools or integers when configured to do so" do
|
268
277
|
MYSQL_DB[:booltest].delete
|
269
278
|
MYSQL_DB[:booltest] << {:value=>true}
|
270
279
|
MYSQL_DB[:booltest].all.should == [{:value=>true}]
|
271
280
|
MYSQL_DB[:booltest].delete
|
272
281
|
MYSQL_DB[:booltest] << {:value=>false}
|
273
282
|
MYSQL_DB[:booltest].all.should == [{:value=>false}]
|
283
|
+
|
284
|
+
Sequel.convert_tinyint_to_bool = false
|
285
|
+
MYSQL_DB[:booltest].delete
|
286
|
+
MYSQL_DB[:booltest] << {:value=>true}
|
287
|
+
MYSQL_DB[:booltest].all.should == [{:value=>1}]
|
288
|
+
MYSQL_DB[:booltest].delete
|
289
|
+
MYSQL_DB[:booltest] << {:value=>false}
|
290
|
+
MYSQL_DB[:booltest].all.should == [{:value=>0}]
|
291
|
+
|
292
|
+
MYSQL_DB[:booltest].delete
|
293
|
+
MYSQL_DB[:booltest] << {:value=>1}
|
294
|
+
MYSQL_DB[:booltest].all.should == [{:value=>1}]
|
295
|
+
MYSQL_DB[:booltest].delete
|
296
|
+
MYSQL_DB[:booltest] << {:value=>0}
|
297
|
+
MYSQL_DB[:booltest].all.should == [{:value=>0}]
|
274
298
|
end
|
275
299
|
end
|
276
300
|
|
@@ -466,17 +490,17 @@ end
|
|
466
490
|
if %w'localhost 127.0.0.1 ::1'.include? MYSQL_URI.host
|
467
491
|
context "A MySQL database" do
|
468
492
|
specify "should accept a socket option" do
|
469
|
-
db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user =>
|
493
|
+
db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user => MYSQL_USER, :socket => MYSQL_SOCKET_FILE)
|
470
494
|
proc {db.test_connection}.should_not raise_error
|
471
495
|
end
|
472
496
|
|
473
497
|
specify "should accept a socket option without host option" do
|
474
|
-
db = Sequel.mysql(MYSQL_DB_NAME, :user =>
|
498
|
+
db = Sequel.mysql(MYSQL_DB_NAME, :user => MYSQL_USER, :socket => MYSQL_SOCKET_FILE)
|
475
499
|
proc {db.test_connection}.should_not raise_error
|
476
500
|
end
|
477
501
|
|
478
502
|
specify "should fail to connect with invalid socket" do
|
479
|
-
db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user =>
|
503
|
+
db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user => MYSQL_USER, :socket => 'blah')
|
480
504
|
proc {db.test_connection}.should raise_error
|
481
505
|
end
|
482
506
|
end
|
@@ -17,6 +17,10 @@ POSTGRES_DB.create_table! :test3 do
|
|
17
17
|
integer :value
|
18
18
|
timestamp :time
|
19
19
|
end
|
20
|
+
POSTGRES_DB.create_table! :test4 do
|
21
|
+
varchar :name, :size => 20
|
22
|
+
bytea :value
|
23
|
+
end
|
20
24
|
|
21
25
|
context "A PostgreSQL database" do
|
22
26
|
setup do
|
@@ -43,6 +47,10 @@ context "A PostgreSQL database" do
|
|
43
47
|
[:value, {:type=>:integer, :allow_null=>true, :max_chars=>nil, :default=>nil, :db_type=>"integer", :numeric_precision=>32}],
|
44
48
|
[:time, {:type=>:datetime, :allow_null=>true, :max_chars=>nil, :default=>nil, :db_type=>"timestamp without time zone", :numeric_precision=>nil}]
|
45
49
|
]
|
50
|
+
@db.schema(:test4, :reload=>true).should == [
|
51
|
+
[:name, {:type=>:string, :allow_null=>true, :max_chars=>20, :default=>nil, :db_type=>"character varying", :numeric_precision=>nil}],
|
52
|
+
[:value, {:type=>:blob, :allow_null=>true, :max_chars=>nil, :default=>nil, :db_type=>"bytea", :numeric_precision=>nil}]
|
53
|
+
]
|
46
54
|
end
|
47
55
|
|
48
56
|
specify "should get the schema all database tables if no table name is used" do
|
@@ -172,6 +180,12 @@ context "A PostgreSQL dataset" do
|
|
172
180
|
@d.count.should == 1
|
173
181
|
end
|
174
182
|
|
183
|
+
specify "should have #transaction yield the connection" do
|
184
|
+
POSTGRES_DB.transaction do |conn|
|
185
|
+
conn.should be_a_kind_of(Sequel::Postgres::Adapter)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
175
189
|
specify "should correctly rollback transactions" do
|
176
190
|
proc do
|
177
191
|
POSTGRES_DB.transaction do
|
@@ -237,9 +251,27 @@ context "A PostgreSQL dataset" do
|
|
237
251
|
@d.filter(:name => /^bc/).count.should == 1
|
238
252
|
end
|
239
253
|
|
240
|
-
specify "should
|
241
|
-
|
242
|
-
|
254
|
+
specify "should correctly escape strings" do
|
255
|
+
POSTGRES_DB['SELECT ? AS a', "\\dingo"].get(:a) == "\\dingo"
|
256
|
+
end
|
257
|
+
|
258
|
+
specify "should properly escape binary data" do
|
259
|
+
POSTGRES_DB['SELECT ? AS a', "\1\2\3".to_blob].get(:a) == "\1\2\3"
|
260
|
+
end
|
261
|
+
|
262
|
+
specify "should retrieve binary data as Blob object" do
|
263
|
+
d = POSTGRES_DB[:test4]
|
264
|
+
d << {:name => '123', :value => "\1\2\3".to_blob}
|
265
|
+
retrieved_binary_value = d[:name => '123'][:value]
|
266
|
+
retrieved_binary_value.should be_a_kind_of(::Sequel::SQL::Blob)
|
267
|
+
retrieved_binary_value.should == "\1\2\3"
|
268
|
+
retrieved_binary_value = d[:value => "\1\2\3".to_blob][:value]
|
269
|
+
retrieved_binary_value.should be_a_kind_of(::Sequel::SQL::Blob)
|
270
|
+
retrieved_binary_value.should == "\1\2\3"
|
271
|
+
end
|
272
|
+
|
273
|
+
specify "should properly receive binary data" do
|
274
|
+
POSTGRES_DB['SELECT ?::bytea AS a', "a"].get(:a) == "a"
|
243
275
|
end
|
244
276
|
end
|
245
277
|
|
@@ -387,8 +387,11 @@ context "A SQLite database" do
|
|
387
387
|
@db[:test2].first.should == {:name => 'mmm', :value => 111, :xyz=>'000'}
|
388
388
|
end
|
389
389
|
|
390
|
-
specify "should
|
391
|
-
|
390
|
+
specify "should support drop_column operations" do
|
391
|
+
@db.drop_column :test2, :value
|
392
|
+
@db[:test2].columns.should == [:name]
|
393
|
+
@db[:test2] << {:name => 'mmm'}
|
394
|
+
@db[:test2].first.should == {:name => 'mmm'}
|
392
395
|
end
|
393
396
|
|
394
397
|
specify "should not support rename_column operations" do
|
@@ -398,4 +401,13 @@ context "A SQLite database" do
|
|
398
401
|
specify "should not support set_column_type operations" do
|
399
402
|
proc {@db.set_column_type :test2, :value, :integer}.should raise_error(Sequel::Error)
|
400
403
|
end
|
404
|
+
|
405
|
+
specify "should support add_index" do
|
406
|
+
@db.add_index :test2, :value, :unique => true
|
407
|
+
@db.add_index :test2, [:name, :value]
|
408
|
+
end
|
409
|
+
|
410
|
+
specify "should not support drop_index" do
|
411
|
+
proc {@db.drop_index :test2, :value}.should raise_error(Sequel::Error)
|
412
|
+
end
|
401
413
|
end
|
data/spec/core_sql_spec.rb
CHANGED
@@ -111,6 +111,17 @@ context "String#lit" do
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
+
context "String#to_blob" do
|
115
|
+
specify "should return a Blob object" do
|
116
|
+
'xyz'.to_blob.should be_a_kind_of(::Sequel::SQL::Blob)
|
117
|
+
'xyz'.to_blob.should == 'xyz'
|
118
|
+
end
|
119
|
+
|
120
|
+
specify "should retain binary data" do
|
121
|
+
"\1\2\3\4".to_blob.should == "\1\2\3\4"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
114
125
|
context "String#split_sql" do
|
115
126
|
specify "should split a string containing multiple statements" do
|
116
127
|
"DROP TABLE a; DROP TABLE c".split_sql.should == \
|
@@ -212,6 +223,13 @@ context "Column references" do
|
|
212
223
|
end
|
213
224
|
end
|
214
225
|
|
226
|
+
context "Blob" do
|
227
|
+
specify "#to_blob should return self" do
|
228
|
+
blob = "x".to_blob
|
229
|
+
blob.to_blob.object_id.should == blob.object_id
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
215
233
|
context "Symbol#*" do
|
216
234
|
setup do
|
217
235
|
@ds = Sequel::Dataset.new(nil)
|
@@ -228,9 +246,26 @@ context "Symbol#*" do
|
|
228
246
|
end
|
229
247
|
end
|
230
248
|
|
231
|
-
context "Symbol
|
232
|
-
|
233
|
-
|
249
|
+
context "Symbol" do
|
250
|
+
before do
|
251
|
+
@ds = Sequel::Dataset.new(nil)
|
252
|
+
@ds.quote_identifiers = true
|
253
|
+
end
|
254
|
+
|
255
|
+
specify "#identifier should format an identifier" do
|
256
|
+
@ds.literal(:xyz__abc.identifier).should == '"XYZ__ABC"'
|
257
|
+
end
|
258
|
+
|
259
|
+
specify "#qualify should format a qualified column" do
|
260
|
+
@ds.literal(:xyz.qualify(:abc)).should == '"ABC"."XYZ"'
|
261
|
+
end
|
262
|
+
|
263
|
+
specify "should be able to qualify an identifier" do
|
264
|
+
@ds.literal(:xyz.identifier.qualify(:xyz__abc)).should == '"XYZ__ABC"."XYZ"'
|
265
|
+
end
|
266
|
+
|
267
|
+
specify "should be able to specify a schema.table.column" do
|
268
|
+
@ds.literal(:column.qualify(:table__name.qualify(:schema))).should == '"SCHEMA"."TABLE__NAME"."COLUMN"'
|
234
269
|
end
|
235
270
|
end
|
236
271
|
|
data/spec/database_spec.rb
CHANGED
@@ -35,6 +35,15 @@ context "A new Database" do
|
|
35
35
|
d.synchronize {|c| cc = c}
|
36
36
|
cc.should == 1234
|
37
37
|
end
|
38
|
+
|
39
|
+
specify "should respect the :quote_identifiers and :single_threaded options" do
|
40
|
+
db = Sequel::Database.new(:quote_identifiers=>false, :single_threaded=>true)
|
41
|
+
db.quote_identifiers?.should == false
|
42
|
+
db.pool.should be_a_kind_of(Sequel::SingleThreadedPool)
|
43
|
+
db = Sequel::Database.new(:quote_identifiers=>true, :single_threaded=>false)
|
44
|
+
db.quote_identifiers?.should == true
|
45
|
+
db.pool.should be_a_kind_of(Sequel::ConnectionPool)
|
46
|
+
end
|
38
47
|
end
|
39
48
|
|
40
49
|
context "Database#connect" do
|
@@ -97,7 +106,7 @@ context "Database#dataset" do
|
|
97
106
|
e.sql.should == 'SELECT * FROM miu'
|
98
107
|
end
|
99
108
|
|
100
|
-
|
109
|
+
specify "should provide a filtered #from dataset if a block is given" do
|
101
110
|
d = @db.from(:mau) {:x > 100}
|
102
111
|
d.should be_a_kind_of(Sequel::Dataset)
|
103
112
|
d.sql.should == 'SELECT * FROM mau WHERE (x > 100)'
|
@@ -587,6 +596,15 @@ context "A Database adapter with a scheme" do
|
|
587
596
|
c.should be_a_kind_of(CCC)
|
588
597
|
c.opts.should == {:adapter => :ccc, :database => 'mydb'}
|
589
598
|
end
|
599
|
+
|
600
|
+
specify "should be accessible through Sequel.connect with URL parameters" do
|
601
|
+
c = Sequel.connect 'ccc://localhost/db?host=/tmp&user=test'
|
602
|
+
c.should be_a_kind_of(CCC)
|
603
|
+
c.opts[:host].should == '/tmp'
|
604
|
+
c.opts[:database].should == 'db'
|
605
|
+
c.opts[:user].should == 'test'
|
606
|
+
end
|
607
|
+
|
590
608
|
end
|
591
609
|
|
592
610
|
context "An unknown database scheme" do
|
data/spec/dataset_spec.rb
CHANGED
@@ -164,11 +164,6 @@ context "A simple dataset" do
|
|
164
164
|
"UPDATE test SET name = 'abc'"
|
165
165
|
end
|
166
166
|
|
167
|
-
pt_specify "should format an update statement with block" do
|
168
|
-
@dataset.update_sql {:x << :y}.should ==
|
169
|
-
"UPDATE test SET x = y"
|
170
|
-
end
|
171
|
-
|
172
167
|
specify "should be able to return rows for arbitrary SQL" do
|
173
168
|
@dataset.select_sql(:sql => 'xxx yyy zzz').should ==
|
174
169
|
"xxx yyy zzz"
|
@@ -271,7 +266,7 @@ context "Dataset#where" do
|
|
271
266
|
"SELECT * FROM test WHERE ((a = 1) AND (d = 4))"
|
272
267
|
end
|
273
268
|
|
274
|
-
|
269
|
+
specify "should be composable using AND operator (for scoping) with block" do
|
275
270
|
@d3.where{:e < 5}.select_sql.should ==
|
276
271
|
"SELECT * FROM test WHERE ((a = 1) AND (e < 5))"
|
277
272
|
end
|
@@ -294,28 +289,11 @@ context "Dataset#where" do
|
|
294
289
|
'SELECT * FROM test WHERE ((table.id >= 4) AND (table.id < 7))'
|
295
290
|
end
|
296
291
|
|
297
|
-
pt_specify "should accept ranges with a block" do
|
298
|
-
@dataset.filter {:id == (4..7)}.sql.should ==
|
299
|
-
'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
|
300
|
-
@dataset.filter {:id.in?(4..7)}.sql.should ==
|
301
|
-
'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
|
302
|
-
|
303
|
-
@dataset.filter {:table__id == (4..7)}.sql.should ==
|
304
|
-
'SELECT * FROM test WHERE (table.id >= 4 AND table.id <= 7)'
|
305
|
-
@dataset.filter {:table__id.in?(4..7)}.sql.should ==
|
306
|
-
'SELECT * FROM test WHERE (table.id >= 4 AND table.id <= 7)'
|
307
|
-
end
|
308
|
-
|
309
292
|
specify "should accept nil" do
|
310
293
|
@dataset.filter(:owner_id => nil).sql.should ==
|
311
294
|
'SELECT * FROM test WHERE (owner_id IS NULL)'
|
312
295
|
end
|
313
296
|
|
314
|
-
pt_specify "should accept nil with a block" do
|
315
|
-
@dataset.filter{:owner_id.nil?}.sql.should ==
|
316
|
-
'SELECT * FROM test WHERE (owner_id IS NULL)'
|
317
|
-
end
|
318
|
-
|
319
297
|
specify "should accept a subquery" do
|
320
298
|
@dataset.filter('gdp > ?', @d1.select(:avg[:gdp])).sql.should ==
|
321
299
|
"SELECT * FROM test WHERE (gdp > (SELECT avg(gdp) FROM test WHERE (region = 'Asia')))"
|
@@ -330,36 +308,24 @@ context "Dataset#where" do
|
|
330
308
|
'SELECT * FROM test WHERE (EXISTS (SELECT * FROM test WHERE (price < 100)))'
|
331
309
|
end
|
332
310
|
|
333
|
-
|
311
|
+
specify "should accept proc expressions" do
|
334
312
|
d = @d1.select(:avg[:gdp])
|
335
313
|
@dataset.filter {:gdp > d}.sql.should ==
|
336
314
|
"SELECT * FROM test WHERE (gdp > (SELECT avg(gdp) FROM test WHERE (region = 'Asia')))"
|
337
315
|
|
338
|
-
@dataset.filter {:id.in(4..7)}.sql.should ==
|
339
|
-
'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
|
340
|
-
|
341
|
-
@dataset.filter {:c == 3}.sql.should ==
|
342
|
-
'SELECT * FROM test WHERE (c = 3)'
|
343
|
-
|
344
|
-
@dataset.filter {:id == :items__id}.sql.should ==
|
345
|
-
'SELECT * FROM test WHERE (id = items.id)'
|
346
|
-
|
347
316
|
@dataset.filter {:a < 1}.sql.should ==
|
348
317
|
'SELECT * FROM test WHERE (a < 1)'
|
349
318
|
|
350
|
-
@dataset.filter {:a
|
351
|
-
'SELECT * FROM test WHERE (NOT (a = 1))'
|
352
|
-
|
353
|
-
@dataset.filter {:a >= 1 && :b <= 2}.sql.should ==
|
319
|
+
@dataset.filter {(:a >= 1) & (:b <= 2)}.sql.should ==
|
354
320
|
'SELECT * FROM test WHERE ((a >= 1) AND (b <= 2))'
|
355
321
|
|
356
322
|
@dataset.filter {:c.like 'ABC%'}.sql.should ==
|
357
323
|
"SELECT * FROM test WHERE (c LIKE 'ABC%')"
|
358
324
|
|
359
|
-
@dataset.filter {:c.like
|
325
|
+
@dataset.filter {:c.like 'ABC%'}.sql.should ==
|
360
326
|
"SELECT * FROM test WHERE (c LIKE 'ABC%')"
|
361
327
|
|
362
|
-
@dataset.filter {:c.like
|
328
|
+
@dataset.filter {:c.like 'ABC%', '%XYZ'}.sql.should ==
|
363
329
|
"SELECT * FROM test WHERE ((c LIKE 'ABC%') OR (c LIKE '%XYZ'))"
|
364
330
|
end
|
365
331
|
|
@@ -375,10 +341,18 @@ context "Dataset#where" do
|
|
375
341
|
"SELECT * FROM test WHERE 'f'"
|
376
342
|
end
|
377
343
|
|
378
|
-
|
344
|
+
specify "should allow the use of blocks and arguments simultaneously" do
|
379
345
|
@dataset.filter(:zz < 3){:yy > 3}.sql.should ==
|
380
346
|
'SELECT * FROM test WHERE ((zz < 3) AND (yy > 3))'
|
381
347
|
end
|
348
|
+
|
349
|
+
specify "should yield a VirtualRow to the block" do
|
350
|
+
x = nil
|
351
|
+
@dataset.filter{|r| x = r; false}
|
352
|
+
x.should be_a_kind_of(Sequel::SQL::VirtualRow)
|
353
|
+
@dataset.filter{|r| ((r.name < 'b') & {r.table__id => 1}) | r.is_active(r.blah, r.xx, r.x__y_z)}.sql.should ==
|
354
|
+
"SELECT * FROM test WHERE (((name < 'b') AND (table.id = 1)) OR is_active(blah, xx, x.y_z))"
|
355
|
+
end
|
382
356
|
end
|
383
357
|
|
384
358
|
context "Dataset#or" do
|
@@ -403,7 +377,7 @@ context "Dataset#or" do
|
|
403
377
|
'SELECT * FROM test WHERE ((x = 1) OR (yy > 3))'
|
404
378
|
end
|
405
379
|
|
406
|
-
|
380
|
+
specify "should accept blocks passed to filter" do
|
407
381
|
@d1.or{:yy > 3}.sql.should ==
|
408
382
|
'SELECT * FROM test WHERE ((x = 1) OR (yy > 3))'
|
409
383
|
end
|
@@ -416,7 +390,7 @@ context "Dataset#or" do
|
|
416
390
|
'SELECT * FROM test WHERE (((x = 1) OR (y = 2)) AND (z = 3))'
|
417
391
|
end
|
418
392
|
|
419
|
-
|
393
|
+
specify "should allow the use of blocks and arguments simultaneously" do
|
420
394
|
@d1.or(:zz < 3){:yy > 3}.sql.should ==
|
421
395
|
'SELECT * FROM test WHERE ((x = 1) OR ((zz < 3) AND (yy > 3)))'
|
422
396
|
end
|
@@ -448,7 +422,7 @@ context "Dataset#and" do
|
|
448
422
|
'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
|
449
423
|
end
|
450
424
|
|
451
|
-
|
425
|
+
specify "should accept blocks passed to filter" do
|
452
426
|
@d1.and {:yy > 3}.sql.should ==
|
453
427
|
'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
|
454
428
|
end
|
@@ -493,14 +467,14 @@ context "Dataset#exclude" do
|
|
493
467
|
"SELECT * FROM test WHERE ((region != 'Asia') AND (name != 'Japan'))"
|
494
468
|
end
|
495
469
|
|
496
|
-
|
497
|
-
@dataset.exclude{:id
|
498
|
-
'SELECT * FROM test WHERE
|
470
|
+
specify "should support proc expressions" do
|
471
|
+
@dataset.exclude{:id < 6}.sql.should ==
|
472
|
+
'SELECT * FROM test WHERE (id >= 6)'
|
499
473
|
end
|
500
474
|
|
501
|
-
|
502
|
-
@dataset.exclude(:id => (7..11)){:id
|
503
|
-
'SELECT * FROM test WHERE (((id < 7) OR (id > 11)) OR
|
475
|
+
specify "should allow the use of blocks and arguments simultaneously" do
|
476
|
+
@dataset.exclude(:id => (7..11)){:id < 6}.sql.should ==
|
477
|
+
'SELECT * FROM test WHERE (((id < 7) OR (id > 11)) OR (id >= 6))'
|
504
478
|
end
|
505
479
|
end
|
506
480
|
|
@@ -540,7 +514,7 @@ context "Dataset#having" do
|
|
540
514
|
"SELECT #{@columns} FROM test GROUP BY region HAVING (sum(population) > 10)"
|
541
515
|
end
|
542
516
|
|
543
|
-
|
517
|
+
specify "should support proc expressions" do
|
544
518
|
@grouped.having {:sum[:population] > 10}.sql.should ==
|
545
519
|
"SELECT #{@columns} FROM test GROUP BY region HAVING (sum(population) > 10)"
|
546
520
|
end
|
@@ -592,6 +566,18 @@ context "Dataset#group_by" do
|
|
592
566
|
specify "should specify the grouping in generated select statement" do
|
593
567
|
@dataset.select_sql.should ==
|
594
568
|
"SELECT * FROM test GROUP BY type_id"
|
569
|
+
@dataset.group_by(:a, :b).select_sql.should ==
|
570
|
+
"SELECT * FROM test GROUP BY a, b"
|
571
|
+
end
|
572
|
+
|
573
|
+
specify "should specify the grouping in generated select statement" do
|
574
|
+
@dataset.group_by(:type_id=>nil).select_sql.should ==
|
575
|
+
"SELECT * FROM test GROUP BY (type_id IS NULL)"
|
576
|
+
end
|
577
|
+
|
578
|
+
specify "should be aliased as #group" do
|
579
|
+
@dataset.group(:type_id=>nil).select_sql.should ==
|
580
|
+
"SELECT * FROM test GROUP BY (type_id IS NULL)"
|
595
581
|
end
|
596
582
|
end
|
597
583
|
|
@@ -829,11 +815,16 @@ context "Dataset#order" do
|
|
829
815
|
'SELECT * FROM test ORDER BY stamp'
|
830
816
|
end
|
831
817
|
|
832
|
-
specify "should accept a string" do
|
818
|
+
specify "should accept a literal string" do
|
833
819
|
@dataset.order('dada ASC'.lit).sql.should ==
|
834
820
|
'SELECT * FROM test ORDER BY dada ASC'
|
835
821
|
end
|
836
822
|
|
823
|
+
specify "should accept a hash as an expression" do
|
824
|
+
@dataset.order(:name=>nil).sql.should ==
|
825
|
+
'SELECT * FROM test ORDER BY (name IS NULL)'
|
826
|
+
end
|
827
|
+
|
837
828
|
specify "should accept a nil to remove ordering" do
|
838
829
|
@dataset.order(:bah).order(nil).sql.should ==
|
839
830
|
'SELECT * FROM test'
|
@@ -1090,7 +1081,7 @@ context "Dataset#uniq" do
|
|
1090
1081
|
specify "should accept an expression list" do
|
1091
1082
|
@dataset.uniq(:a, :b).sql.should == 'SELECT DISTINCT ON (a, b) name FROM test'
|
1092
1083
|
|
1093
|
-
@dataset.uniq(:stamp.cast_as(:integer), :node_id).sql.should == 'SELECT DISTINCT ON (cast(stamp AS integer), node_id) name FROM test'
|
1084
|
+
@dataset.uniq(:stamp.cast_as(:integer), :node_id=>nil).sql.should == 'SELECT DISTINCT ON (cast(stamp AS integer), (node_id IS NULL)) name FROM test'
|
1094
1085
|
end
|
1095
1086
|
|
1096
1087
|
specify "should do a subselect for count" do
|
@@ -1133,6 +1124,11 @@ context "Dataset#count" do
|
|
1133
1124
|
@dataset.count.should == 1
|
1134
1125
|
@c.sql.should == "SELECT COUNT(*) FROM (select abc from xyz) t1 LIMIT 1"
|
1135
1126
|
end
|
1127
|
+
|
1128
|
+
specify "should return limit if count is greater than it" do
|
1129
|
+
@dataset.limit(5).count.should == 1
|
1130
|
+
@c.sql.should == "SELECT COUNT(*) FROM (SELECT * FROM test LIMIT 5) t1 LIMIT 1"
|
1131
|
+
end
|
1136
1132
|
end
|
1137
1133
|
|
1138
1134
|
|
@@ -1475,14 +1471,6 @@ context "Dataset#set" do
|
|
1475
1471
|
@d.set({:x => 3})
|
1476
1472
|
@d.last_sql.should == 'UPDATE items SET x = 3'
|
1477
1473
|
end
|
1478
|
-
|
1479
|
-
pt_specify "should accept a block" do
|
1480
|
-
@d.set{:x << :x + 1}
|
1481
|
-
@d.last_sql.should == 'UPDATE items SET x = (x + 1)'
|
1482
|
-
|
1483
|
-
@d.set{(:x|1) << (:x|2) + 1}
|
1484
|
-
@d.last_sql.should == 'UPDATE items SET x[1] = (x[2] + 1)'
|
1485
|
-
end
|
1486
1474
|
end
|
1487
1475
|
|
1488
1476
|
|
@@ -1629,17 +1617,17 @@ context "Dataset #first and #last" do
|
|
1629
1617
|
r = @d.order(:a).last(i).should == [[:a,1,:b,2, "SELECT * FROM test ORDER BY a DESC LIMIT #{i}"]] * i
|
1630
1618
|
end
|
1631
1619
|
|
1632
|
-
|
1620
|
+
specify "should return the first matching record if a block is given without an argument" do
|
1633
1621
|
@d.first{:z > 26}.should == [:a,1,:b,2, 'SELECT * FROM test WHERE (z > 26) LIMIT 1']
|
1634
1622
|
@d.order(:name).last{:z > 26}.should == [:a,1,:b,2, 'SELECT * FROM test WHERE (z > 26) ORDER BY name DESC LIMIT 1']
|
1635
1623
|
end
|
1636
1624
|
|
1637
|
-
|
1625
|
+
specify "should combine block and standard argument filters if argument is not an Integer" do
|
1638
1626
|
@d.first(:y=>25){:z > 26}.should == [:a,1,:b,2, 'SELECT * FROM test WHERE ((z > 26) AND (y = 25)) LIMIT 1']
|
1639
1627
|
@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']
|
1640
1628
|
end
|
1641
1629
|
|
1642
|
-
|
1630
|
+
specify "should filter and return an array of records if an Integer argument is provided and a block is given" do
|
1643
1631
|
i = rand(10) + 10
|
1644
1632
|
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
|
1645
1633
|
i = rand(10) + 10
|
@@ -2205,6 +2193,12 @@ context "Dataset#columns" do
|
|
2205
2193
|
@dataset.opts[:from] = [:nana]
|
2206
2194
|
@dataset.columns.should == 'SELECT * FROM items LIMIT 1a'
|
2207
2195
|
end
|
2196
|
+
|
2197
|
+
specify "should ignore any filters, orders, or DISTINCT clauses" do
|
2198
|
+
@dataset.filter!(:b=>100).order!(:b).distinct!(:b)
|
2199
|
+
@dataset.columns = nil
|
2200
|
+
@dataset.columns.should == 'SELECT * FROM items LIMIT 1a'
|
2201
|
+
end
|
2208
2202
|
end
|
2209
2203
|
|
2210
2204
|
context "Dataset#columns!" do
|
@@ -2487,9 +2481,9 @@ context "Dataset" do
|
|
2487
2481
|
@d.sql.should == "SELECT * FROM x WHERE (y = 1)"
|
2488
2482
|
end
|
2489
2483
|
|
2490
|
-
|
2491
|
-
@d.filter!{:y
|
2492
|
-
@d.sql.should == "SELECT * FROM x WHERE (y
|
2484
|
+
specify "should support self-changing filter! with block" do
|
2485
|
+
@d.filter!{:y < 2}
|
2486
|
+
@d.sql.should == "SELECT * FROM x WHERE (y < 2)"
|
2493
2487
|
end
|
2494
2488
|
|
2495
2489
|
specify "should raise for ! methods that don't return a dataset" do
|