sequel 3.10.0 → 3.11.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 +68 -0
- data/COPYING +1 -1
- data/README.rdoc +87 -27
- data/bin/sequel +2 -4
- data/doc/association_basics.rdoc +1383 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/opening_databases.rdoc +45 -16
- data/doc/querying.rdoc +210 -0
- data/doc/release_notes/3.11.0.txt +254 -0
- data/doc/virtual_rows.rdoc +217 -31
- data/lib/sequel/adapters/ado.rb +28 -12
- data/lib/sequel/adapters/ado/mssql.rb +33 -1
- data/lib/sequel/adapters/amalgalite.rb +13 -8
- data/lib/sequel/adapters/db2.rb +1 -2
- data/lib/sequel/adapters/dbi.rb +7 -4
- data/lib/sequel/adapters/do.rb +14 -15
- data/lib/sequel/adapters/do/postgres.rb +4 -5
- data/lib/sequel/adapters/do/sqlite.rb +9 -0
- data/lib/sequel/adapters/firebird.rb +5 -10
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +111 -49
- data/lib/sequel/adapters/jdbc/mssql.rb +1 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +4 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +8 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +12 -0
- data/lib/sequel/adapters/mysql.rb +14 -5
- data/lib/sequel/adapters/odbc.rb +2 -4
- data/lib/sequel/adapters/odbc/mssql.rb +2 -4
- data/lib/sequel/adapters/openbase.rb +1 -2
- data/lib/sequel/adapters/oracle.rb +4 -8
- data/lib/sequel/adapters/postgres.rb +4 -11
- data/lib/sequel/adapters/shared/mssql.rb +22 -9
- data/lib/sequel/adapters/shared/mysql.rb +33 -30
- data/lib/sequel/adapters/shared/oracle.rb +0 -5
- data/lib/sequel/adapters/shared/postgres.rb +13 -11
- data/lib/sequel/adapters/shared/sqlite.rb +56 -10
- data/lib/sequel/adapters/sqlite.rb +16 -9
- data/lib/sequel/connection_pool.rb +6 -1
- data/lib/sequel/connection_pool/single.rb +1 -0
- data/lib/sequel/core.rb +6 -1
- data/lib/sequel/database.rb +52 -23
- data/lib/sequel/database/schema_generator.rb +6 -0
- data/lib/sequel/database/schema_methods.rb +5 -5
- data/lib/sequel/database/schema_sql.rb +1 -1
- data/lib/sequel/dataset.rb +4 -190
- data/lib/sequel/dataset/actions.rb +323 -1
- data/lib/sequel/dataset/features.rb +18 -2
- data/lib/sequel/dataset/graph.rb +7 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +6 -0
- data/lib/sequel/dataset/query.rb +272 -6
- data/lib/sequel/dataset/sql.rb +186 -394
- data/lib/sequel/model.rb +4 -2
- data/lib/sequel/model/associations.rb +31 -14
- data/lib/sequel/model/base.rb +32 -13
- data/lib/sequel/model/exceptions.rb +8 -4
- data/lib/sequel/model/plugins.rb +3 -13
- data/lib/sequel/plugins/active_model.rb +26 -7
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/optimistic_locking.rb +25 -9
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +26 -0
- data/spec/adapters/mysql_spec.rb +33 -4
- data/spec/adapters/postgres_spec.rb +24 -1
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/adapters/sqlite_spec.rb +28 -0
- data/spec/core/connection_pool_spec.rb +17 -5
- data/spec/core/database_spec.rb +101 -1
- data/spec/core/dataset_spec.rb +42 -4
- data/spec/core/schema_spec.rb +13 -0
- data/spec/extensions/active_model_spec.rb +34 -11
- data/spec/extensions/caching_spec.rb +2 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/spec_helper.rb +2 -0
- data/spec/integration/dataset_test.rb +12 -1
- data/spec/integration/model_test.rb +12 -0
- data/spec/integration/plugin_test.rb +61 -1
- data/spec/integration/schema_test.rb +14 -3
- data/spec/model/base_spec.rb +27 -0
- data/spec/model/plugins_spec.rb +0 -22
- data/spec/model/record_spec.rb +32 -1
- data/spec/model/spec_helper.rb +2 -0
- metadata +14 -3
- data/lib/sequel/dataset/convenience.rb +0 -326
data/lib/sequel/version.rb
CHANGED
data/spec/adapters/mssql_spec.rb
CHANGED
@@ -375,3 +375,29 @@ context "MSSSQL::Dataset#into" do
|
|
375
375
|
@db.drop_table(:new)
|
376
376
|
end
|
377
377
|
end
|
378
|
+
|
379
|
+
context "A MSSQL database" do
|
380
|
+
before do
|
381
|
+
@db = MSSQL_DB
|
382
|
+
end
|
383
|
+
after do
|
384
|
+
@db.drop_table(:a)
|
385
|
+
end
|
386
|
+
|
387
|
+
specify "should handle many existing types for set_column_allow_null" do
|
388
|
+
@db.create_table!(:a){column :a, 'integer'}
|
389
|
+
@db.alter_table(:a){set_column_allow_null :a, false}
|
390
|
+
@db.create_table!(:a){column :a, 'decimal(24, 2)'}
|
391
|
+
@db.alter_table(:a){set_column_allow_null :a, false}
|
392
|
+
@db.schema(:a).first.last[:column_size].should == 24
|
393
|
+
@db.schema(:a).first.last[:scale].should == 2
|
394
|
+
@db.create_table!(:a){column :a, 'decimal(10)'}
|
395
|
+
@db.schema(:a).first.last[:column_size].should == 10
|
396
|
+
@db.schema(:a).first.last[:scale].should == 0
|
397
|
+
@db.alter_table(:a){set_column_allow_null :a, false}
|
398
|
+
@db.create_table!(:a){column :a, 'nchar(2)'}
|
399
|
+
@db.alter_table(:a){set_column_allow_null :a, false}
|
400
|
+
s = @db.schema(:a).first.last
|
401
|
+
(s[:max_chars] || s[:column_size]).should == 2
|
402
|
+
end
|
403
|
+
end
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -107,14 +107,20 @@ if MYSQL_DB.class.adapter_scheme == :mysql
|
|
107
107
|
@db.schema(:booltest, :reload=>true).should == [[:b, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(1)"}, ], [:i, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(4)"}, ]]
|
108
108
|
end
|
109
109
|
|
110
|
-
specify "should return
|
110
|
+
specify "should return tinyint(1)s as bools and tinyint(4)s as integers when set" do
|
111
|
+
Sequel::MySQL.convert_tinyint_to_bool = true
|
111
112
|
@ds.delete
|
112
113
|
@ds << {:b=>true, :i=>10}
|
113
|
-
@ds.all.should == [{:b=>true, :i=>
|
114
|
+
@ds.all.should == [{:b=>true, :i=>10}]
|
114
115
|
@ds.delete
|
115
116
|
@ds << {:b=>false, :i=>0}
|
116
|
-
@ds.all.should == [{:b=>false, :i=>
|
117
|
-
|
117
|
+
@ds.all.should == [{:b=>false, :i=>0}]
|
118
|
+
@ds.delete
|
119
|
+
@ds << {:b=>true, :i=>1}
|
120
|
+
@ds.all.should == [{:b=>true, :i=>1}]
|
121
|
+
end
|
122
|
+
|
123
|
+
specify "should return all tinyints as integers when unset" do
|
118
124
|
Sequel::MySQL.convert_tinyint_to_bool = false
|
119
125
|
@ds.delete
|
120
126
|
@ds << {:b=>true, :i=>10}
|
@@ -244,6 +250,29 @@ context "MySQL datasets" do
|
|
244
250
|
end
|
245
251
|
end
|
246
252
|
|
253
|
+
describe "Dataset#distinct" do
|
254
|
+
before do
|
255
|
+
@db = MYSQL_DB
|
256
|
+
@db.create_table!(:a) do
|
257
|
+
Integer :a
|
258
|
+
Integer :b
|
259
|
+
end
|
260
|
+
@ds = @db[:a]
|
261
|
+
end
|
262
|
+
after do
|
263
|
+
@db.drop_table(:a)
|
264
|
+
end
|
265
|
+
|
266
|
+
it "#distinct with arguments should return results distinct on those arguments" do
|
267
|
+
@ds.insert(20, 10)
|
268
|
+
@ds.insert(30, 10)
|
269
|
+
@ds.order(:b, :a).distinct.map(:a).should == [20, 30]
|
270
|
+
@ds.order(:b, :a.desc).distinct.map(:a).should == [30, 20]
|
271
|
+
# MySQL doesn't respect orders when using the nonstandard GROUP BY
|
272
|
+
[[20], [30]].should include(@ds.order(:b, :a).distinct(:b).map(:a))
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
247
276
|
context "MySQL join expressions" do
|
248
277
|
before do
|
249
278
|
@ds = MYSQL_DB[:nodes]
|
@@ -148,6 +148,29 @@ context "A PostgreSQL dataset" do
|
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
151
|
+
describe "Dataset#distinct" do
|
152
|
+
before do
|
153
|
+
@db = POSTGRES_DB
|
154
|
+
@db.create_table!(:a) do
|
155
|
+
Integer :a
|
156
|
+
Integer :b
|
157
|
+
end
|
158
|
+
@ds = @db[:a]
|
159
|
+
end
|
160
|
+
after do
|
161
|
+
@db.drop_table(:a)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "#distinct with arguments should return results distinct on those arguments" do
|
165
|
+
@ds.insert(20, 10)
|
166
|
+
@ds.insert(30, 10)
|
167
|
+
@ds.order(:b, :a).distinct.map(:a).should == [20, 30]
|
168
|
+
@ds.order(:b, :a.desc).distinct.map(:a).should == [30, 20]
|
169
|
+
@ds.order(:b, :a).distinct(:b).map(:a).should == [20]
|
170
|
+
@ds.order(:b, :a.desc).distinct(:b).map(:a).should == [30]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
151
174
|
if POSTGRES_DB.pool.respond_to?(:max_size) and POSTGRES_DB.pool.max_size > 1
|
152
175
|
describe "Dataset#for_update support" do
|
153
176
|
before do
|
@@ -194,7 +217,7 @@ if POSTGRES_DB.pool.respond_to?(:max_size) and POSTGRES_DB.pool.max_size > 1
|
|
194
217
|
c = @ds.for_share.filter(:id=>1).first
|
195
218
|
end
|
196
219
|
end
|
197
|
-
sleep 0.
|
220
|
+
sleep 0.1
|
198
221
|
@ds.filter(:id=>1).update(:name=>'Jim')
|
199
222
|
c.should == {:id=>1, :number=>20, :name=>nil}
|
200
223
|
end
|
@@ -36,6 +36,34 @@ context "An SQLite database" do
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
specify "should provide the SQLite version as an integer" do
|
40
|
+
@db.sqlite_version.should be_a_kind_of(Integer)
|
41
|
+
end
|
42
|
+
|
43
|
+
specify "should support setting and getting the foreign_keys pragma" do
|
44
|
+
(@db.sqlite_version >= 30619 ? [true, false] : [nil]).should include(@db.foreign_keys)
|
45
|
+
@db.foreign_keys = true
|
46
|
+
@db.foreign_keys = false
|
47
|
+
end
|
48
|
+
|
49
|
+
if SQLITE_DB.sqlite_version >= 30619
|
50
|
+
specify "should enforce foreign key integrity if foreign_keys pragma is set" do
|
51
|
+
@db.foreign_keys = true
|
52
|
+
@db.create_table!(:fk){primary_key :id; foreign_key :parent_id, :fk}
|
53
|
+
@db[:fk].insert(1, nil)
|
54
|
+
@db[:fk].insert(2, 1)
|
55
|
+
@db[:fk].insert(3, 3)
|
56
|
+
proc{@db[:fk].insert(4, 5)}.should raise_error(Sequel::Error)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
specify "should not enforce foreign key integrity if foreign_keys pragma is unset" do
|
61
|
+
@db.foreign_keys = false
|
62
|
+
@db.create_table!(:fk){primary_key :id; foreign_key :parent_id, :fk}
|
63
|
+
@db[:fk].insert(1, 2)
|
64
|
+
@db[:fk].all.should == [{:id=>1, :parent_id=>2}]
|
65
|
+
end
|
66
|
+
|
39
67
|
specify "should provide a list of existing tables" do
|
40
68
|
@db.drop_table(:testing) rescue nil
|
41
69
|
@db.tables.should be_a_kind_of(Array)
|
@@ -240,8 +240,8 @@ shared_examples_for "A threaded connection pool" do
|
|
240
240
|
threads = []
|
241
241
|
stop = nil
|
242
242
|
|
243
|
-
5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.
|
244
|
-
sleep 0.
|
243
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.02;end}}; sleep 0.02}
|
244
|
+
sleep 0.04
|
245
245
|
threads.each {|t| t.should be_alive}
|
246
246
|
cc.size.should == 5
|
247
247
|
@invoked_count.should == 5
|
@@ -253,16 +253,16 @@ shared_examples_for "A threaded connection pool" do
|
|
253
253
|
@pool.allocated.should == h
|
254
254
|
|
255
255
|
threads[0].raise "your'e dead"
|
256
|
-
sleep 0.
|
256
|
+
sleep 0.02
|
257
257
|
threads[3].raise "your'e dead too"
|
258
258
|
|
259
|
-
sleep 0.
|
259
|
+
sleep 0.02
|
260
260
|
|
261
261
|
@pool.available_connections.should == [1, 4]
|
262
262
|
@pool.allocated.should == {threads[1]=>2, threads[2]=>3, threads[4]=>5}
|
263
263
|
|
264
264
|
stop = true
|
265
|
-
sleep 0.
|
265
|
+
sleep 0.04
|
266
266
|
|
267
267
|
@pool.available_connections.size.should == 5
|
268
268
|
@pool.allocated.should be_empty
|
@@ -734,6 +734,12 @@ context "A single threaded pool with multiple servers" do
|
|
734
734
|
end
|
735
735
|
|
736
736
|
shared_examples_for "All connection pools classes" do
|
737
|
+
specify "should not raise an error when disconnecting twice" do
|
738
|
+
c = @class.new({}){123}
|
739
|
+
proc{c.disconnect}.should_not raise_error
|
740
|
+
proc{c.disconnect}.should_not raise_error
|
741
|
+
end
|
742
|
+
|
737
743
|
specify "should yield a connection created by the initialize block to hold" do
|
738
744
|
x = nil
|
739
745
|
@class.new({}){123}.hold{|c| x = c}
|
@@ -746,6 +752,12 @@ shared_examples_for "All connection pools classes" do
|
|
746
752
|
x.should == [:default, :default]
|
747
753
|
end
|
748
754
|
|
755
|
+
specify "should have respect an :after_connect proc that is called with each newly created connection" do
|
756
|
+
x = nil
|
757
|
+
@class.new(:after_connect=>proc{|c| x = [c, c]}){|c| 123}.hold{}
|
758
|
+
x.should == [123, 123]
|
759
|
+
end
|
760
|
+
|
749
761
|
specify "should raise a DatabaseConnectionError if the connection raises an exception" do
|
750
762
|
proc{@class.new({}){|c| raise Exception}.hold{}}.should raise_error(Sequel::DatabaseConnectionError)
|
751
763
|
end
|
data/spec/core/database_spec.rb
CHANGED
@@ -209,6 +209,88 @@ context "Database#connect" do
|
|
209
209
|
end
|
210
210
|
end
|
211
211
|
|
212
|
+
context "Database#log_info" do
|
213
|
+
before do
|
214
|
+
@o = Object.new
|
215
|
+
def @o.logs; @logs || []; end
|
216
|
+
def @o.method_missing(*args); (@logs ||= []) << args; end
|
217
|
+
@db = Sequel::Database.new(:logger=>@o)
|
218
|
+
end
|
219
|
+
|
220
|
+
specify "should log message at info level to all loggers" do
|
221
|
+
@db.log_info('blah')
|
222
|
+
@o.logs.should == [[:info, 'blah']]
|
223
|
+
end
|
224
|
+
|
225
|
+
specify "should log message with args at info level to all loggers" do
|
226
|
+
@db.log_info('blah', [1, 2])
|
227
|
+
@o.logs.should == [[:info, 'blah; [1, 2]']]
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context "Database#log_yield" do
|
232
|
+
before do
|
233
|
+
@o = Object.new
|
234
|
+
def @o.logs; @logs || []; end
|
235
|
+
def @o.warn(*args); (@logs ||= []) << [:warn] + args; end
|
236
|
+
def @o.method_missing(*args); (@logs ||= []) << args; end
|
237
|
+
@db = Sequel::Database.new(:logger=>@o)
|
238
|
+
end
|
239
|
+
|
240
|
+
specify "should yield to the passed block" do
|
241
|
+
a = nil
|
242
|
+
@db.log_yield('blah'){a = 1}
|
243
|
+
a.should == 1
|
244
|
+
end
|
245
|
+
|
246
|
+
specify "should raise an exception if a block is not passed" do
|
247
|
+
proc{@db.log_yield('blah')}.should raise_error
|
248
|
+
end
|
249
|
+
|
250
|
+
specify "should log message with duration at info level to all loggers" do
|
251
|
+
@db.log_yield('blah'){}
|
252
|
+
@o.logs.length.should == 1
|
253
|
+
@o.logs.first.length.should == 2
|
254
|
+
@o.logs.first.first.should == :info
|
255
|
+
@o.logs.first.last.should =~ /\A\(\d\.\d{6}s\) blah\z/
|
256
|
+
end
|
257
|
+
|
258
|
+
specify "should log message with duration at warn level if duration greater than log_warn_duration" do
|
259
|
+
@db.log_warn_duration = 0
|
260
|
+
@db.log_yield('blah'){}
|
261
|
+
@o.logs.length.should == 1
|
262
|
+
@o.logs.first.length.should == 2
|
263
|
+
@o.logs.first.first.should == :warn
|
264
|
+
@o.logs.first.last.should =~ /\A\(\d\.\d{6}s\) blah\z/
|
265
|
+
end
|
266
|
+
|
267
|
+
specify "should log message with duration at info level if duration less than log_warn_duration" do
|
268
|
+
@db.log_warn_duration = 1000
|
269
|
+
@db.log_yield('blah'){}
|
270
|
+
@o.logs.length.should == 1
|
271
|
+
@o.logs.first.length.should == 2
|
272
|
+
@o.logs.first.first.should == :info
|
273
|
+
@o.logs.first.last.should =~ /\A\(\d\.\d{6}s\) blah\z/
|
274
|
+
end
|
275
|
+
|
276
|
+
specify "should log message at error level if block raises an error" do
|
277
|
+
@db.log_warn_duration = 0
|
278
|
+
proc{@db.log_yield('blah'){raise Sequel::Error, 'adsf'}}.should raise_error
|
279
|
+
@o.logs.length.should == 1
|
280
|
+
@o.logs.first.length.should == 2
|
281
|
+
@o.logs.first.first.should == :error
|
282
|
+
@o.logs.first.last.should =~ /\ASequel::Error: adsf: blah\z/
|
283
|
+
end
|
284
|
+
|
285
|
+
specify "should include args with message if args passed" do
|
286
|
+
@db.log_yield('blah', [1, 2]){}
|
287
|
+
@o.logs.length.should == 1
|
288
|
+
@o.logs.first.length.should == 2
|
289
|
+
@o.logs.first.first.should == :info
|
290
|
+
@o.logs.first.last.should =~ /\A\(\d\.\d{6}s\) blah; \[1, 2\]\z/
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
212
294
|
context "Database#uri" do
|
213
295
|
before do
|
214
296
|
@c = Class.new(Sequel::Database) do
|
@@ -342,7 +424,7 @@ context "Database#test_connection" do
|
|
342
424
|
@db = Sequel::Database.new{@test = rand(100)}
|
343
425
|
end
|
344
426
|
|
345
|
-
specify "should
|
427
|
+
specify "should pool#hold" do
|
346
428
|
@db.test_connection
|
347
429
|
@test.should_not be_nil
|
348
430
|
end
|
@@ -350,6 +432,10 @@ context "Database#test_connection" do
|
|
350
432
|
specify "should return true if successful" do
|
351
433
|
@db.test_connection.should be_true
|
352
434
|
end
|
435
|
+
|
436
|
+
specify "should raise an error if the attempting to connect raises an error" do
|
437
|
+
proc{Sequel::Database.new{raise Sequel::Error, 'blah'}.test_connection}.should raise_error(Sequel::Error)
|
438
|
+
end
|
353
439
|
end
|
354
440
|
|
355
441
|
class DummyDataset < Sequel::Dataset
|
@@ -875,6 +961,20 @@ context "A Database adapter with a scheme" do
|
|
875
961
|
c.opts[:database].should == 'd[b]'
|
876
962
|
c.opts[:host].should == 'domain\\instance'
|
877
963
|
end
|
964
|
+
|
965
|
+
specify "should test the connection if test parameter is truthy" do
|
966
|
+
proc{Sequel.connect 'ccc:///d%5bb%5d?test=t'}.should raise_error(Sequel::DatabaseConnectionError)
|
967
|
+
proc{Sequel.connect 'ccc:///d%5bb%5d?test=1'}.should raise_error(Sequel::DatabaseConnectionError)
|
968
|
+
proc{Sequel.connect 'ccc:///d%5bb%5d', :test=>true}.should raise_error(Sequel::DatabaseConnectionError)
|
969
|
+
proc{Sequel.connect 'ccc:///d%5bb%5d', :test=>'t'}.should raise_error(Sequel::DatabaseConnectionError)
|
970
|
+
end
|
971
|
+
|
972
|
+
specify "should not test the connection if test parameter is not truthy" do
|
973
|
+
proc{Sequel.connect 'ccc:///d%5bb%5d?test=f'}.should_not raise_error
|
974
|
+
proc{Sequel.connect 'ccc:///d%5bb%5d?test=0'}.should_not raise_error
|
975
|
+
proc{Sequel.connect 'ccc:///d%5bb%5d', :test=>false}.should_not raise_error
|
976
|
+
proc{Sequel.connect 'ccc:///d%5bb%5d', :test=>'f'}.should_not raise_error
|
977
|
+
end
|
878
978
|
end
|
879
979
|
|
880
980
|
context "Sequel::Database.connect" do
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -322,6 +322,16 @@ context "Dataset#where" do
|
|
322
322
|
@d3 = @dataset.where("a = 1")
|
323
323
|
end
|
324
324
|
|
325
|
+
specify "should just clone if given an empty argument" do
|
326
|
+
@dataset.where({}).sql.should == @dataset.sql
|
327
|
+
@dataset.where([]).sql.should == @dataset.sql
|
328
|
+
@dataset.where('').sql.should == @dataset.sql
|
329
|
+
|
330
|
+
@dataset.filter({}).sql.should == @dataset.sql
|
331
|
+
@dataset.filter([]).sql.should == @dataset.sql
|
332
|
+
@dataset.filter('').sql.should == @dataset.sql
|
333
|
+
end
|
334
|
+
|
325
335
|
specify "should work with hashes" do
|
326
336
|
@dataset.where(:name => 'xyz', :price => 342).select_sql.
|
327
337
|
should match(/WHERE \(\(name = 'xyz'\) AND \(price = 342\)\)|WHERE \(\(price = 342\) AND \(name = 'xyz'\)\)/)
|
@@ -735,6 +745,12 @@ context "Dataset#having" do
|
|
735
745
|
@columns = "region, sum(population), avg(gdp)"
|
736
746
|
end
|
737
747
|
|
748
|
+
specify "should just clone if given an empty argument" do
|
749
|
+
@dataset.having({}).sql.should == @dataset.sql
|
750
|
+
@dataset.having([]).sql.should == @dataset.sql
|
751
|
+
@dataset.having('').sql.should == @dataset.sql
|
752
|
+
end
|
753
|
+
|
738
754
|
specify "should affect select statements" do
|
739
755
|
@d1.select_sql.should ==
|
740
756
|
"SELECT #{@columns} FROM test GROUP BY region HAVING (sum(population) > 10)"
|
@@ -1151,6 +1167,28 @@ context "Dataset#select_more" do
|
|
1151
1167
|
end
|
1152
1168
|
end
|
1153
1169
|
|
1170
|
+
context "Dataset#select_append" do
|
1171
|
+
before do
|
1172
|
+
@d = Sequel::Dataset.new(nil).from(:test)
|
1173
|
+
end
|
1174
|
+
|
1175
|
+
specify "should select * in addition to columns if no columns selected" do
|
1176
|
+
@d.select_append(:a, :b).sql.should == 'SELECT *, a, b FROM test'
|
1177
|
+
@d.select_all.select_append(:a, :b).sql.should == 'SELECT *, a, b FROM test'
|
1178
|
+
@d.select(:blah).select_all.select_append(:a, :b).sql.should == 'SELECT *, a, b FROM test'
|
1179
|
+
end
|
1180
|
+
|
1181
|
+
specify "should add to the currently selected columns" do
|
1182
|
+
@d.select(:a).select_append(:b).sql.should == 'SELECT a, b FROM test'
|
1183
|
+
@d.select(:a.*).select_append(:b.*).sql.should == 'SELECT a.*, b.* FROM test'
|
1184
|
+
end
|
1185
|
+
|
1186
|
+
specify "should accept a block that yields a virtual row" do
|
1187
|
+
@d.select(:a).select_append{|o| o.b}.sql.should == 'SELECT a, b FROM test'
|
1188
|
+
@d.select(:a.*).select_append(:b.*){b(1)}.sql.should == 'SELECT a.*, b.*, b(1) FROM test'
|
1189
|
+
end
|
1190
|
+
end
|
1191
|
+
|
1154
1192
|
context "Dataset#order" do
|
1155
1193
|
before do
|
1156
1194
|
@dataset = Sequel::Dataset.new(nil).from(:test)
|
@@ -1484,13 +1522,13 @@ context "Dataset#distinct" do
|
|
1484
1522
|
@dataset.distinct.sql.should == 'SELECT DISTINCT name FROM test'
|
1485
1523
|
end
|
1486
1524
|
|
1487
|
-
specify "should raise an error if columns given and
|
1488
|
-
@dataset.meta_def(:supports_distinct_on?){false}
|
1525
|
+
specify "should raise an error if columns given and DISTINCT ON is not supported" do
|
1489
1526
|
proc{@dataset.distinct}.should_not raise_error
|
1490
1527
|
proc{@dataset.distinct(:a)}.should raise_error(Sequel::InvalidOperation)
|
1491
1528
|
end
|
1492
1529
|
|
1493
|
-
specify "should
|
1530
|
+
specify "should use DISTINCT ON if columns are given and DISTINCT ON is supported" do
|
1531
|
+
@dataset.meta_def(:supports_distinct_on?){true}
|
1494
1532
|
@dataset.distinct(:a, :b).sql.should == 'SELECT DISTINCT ON (a, b) name FROM test'
|
1495
1533
|
@dataset.distinct(:stamp.cast(:integer), :node_id=>nil).sql.should == 'SELECT DISTINCT ON (CAST(stamp AS integer), (node_id IS NULL)) name FROM test'
|
1496
1534
|
end
|
@@ -2541,7 +2579,7 @@ context "Dataset#columns" do
|
|
2541
2579
|
end
|
2542
2580
|
|
2543
2581
|
specify "should ignore any filters, orders, or DISTINCT clauses" do
|
2544
|
-
@dataset.filter!(:b=>100).order!(:b).distinct!
|
2582
|
+
@dataset.filter!(:b=>100).order!(:b).distinct!
|
2545
2583
|
@dataset.columns = nil
|
2546
2584
|
@dataset.columns.should == 'SELECT * FROM items LIMIT 1a'
|
2547
2585
|
end
|