sequel 3.35.0 → 3.36.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 +78 -0
- data/Rakefile +3 -3
- data/bin/sequel +3 -1
- data/doc/advanced_associations.rdoc +154 -11
- data/doc/migration.rdoc +18 -0
- data/doc/object_model.rdoc +541 -0
- data/doc/opening_databases.rdoc +4 -1
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/schema_modification.rdoc +0 -6
- data/lib/sequel/adapters/do/mysql.rb +7 -0
- data/lib/sequel/adapters/jdbc.rb +11 -3
- data/lib/sequel/adapters/jdbc/mysql.rb +3 -5
- data/lib/sequel/adapters/jdbc/postgresql.rb +10 -8
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/mock.rb +2 -6
- data/lib/sequel/adapters/mysql.rb +3 -9
- data/lib/sequel/adapters/mysql2.rb +12 -11
- data/lib/sequel/adapters/postgres.rb +32 -40
- data/lib/sequel/adapters/shared/mssql.rb +15 -11
- data/lib/sequel/adapters/shared/mysql.rb +28 -3
- data/lib/sequel/adapters/shared/oracle.rb +5 -0
- data/lib/sequel/adapters/shared/postgres.rb +59 -5
- data/lib/sequel/adapters/shared/sqlite.rb +3 -13
- data/lib/sequel/adapters/sqlite.rb +0 -7
- data/lib/sequel/adapters/swift/mysql.rb +2 -5
- data/lib/sequel/adapters/tinytds.rb +1 -2
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -1
- data/lib/sequel/connection_pool/threaded.rb +9 -1
- data/lib/sequel/database/dataset_defaults.rb +3 -1
- data/lib/sequel/database/misc.rb +7 -1
- data/lib/sequel/database/query.rb +11 -3
- data/lib/sequel/database/schema_generator.rb +40 -9
- data/lib/sequel/database/schema_methods.rb +6 -1
- data/lib/sequel/dataset/actions.rb +5 -5
- data/lib/sequel/dataset/prepared_statements.rb +3 -1
- data/lib/sequel/dataset/query.rb +1 -1
- data/lib/sequel/extensions/migration.rb +28 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +0 -9
- data/lib/sequel/extensions/pg_inet.rb +89 -0
- data/lib/sequel/extensions/pg_json.rb +178 -0
- data/lib/sequel/extensions/schema_dumper.rb +24 -6
- data/lib/sequel/model/associations.rb +19 -15
- data/lib/sequel/model/base.rb +11 -12
- data/lib/sequel/plugins/composition.rb +1 -2
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/json_serializer.rb +41 -4
- data/lib/sequel/plugins/nested_attributes.rb +72 -52
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +271 -1
- data/spec/adapters/sqlite_spec.rb +11 -0
- data/spec/core/connection_pool_spec.rb +26 -1
- data/spec/core/database_spec.rb +19 -0
- data/spec/core/dataset_spec.rb +45 -5
- data/spec/core/expression_filters_spec.rb +31 -67
- data/spec/core/mock_adapter_spec.rb +4 -0
- data/spec/extensions/core_extensions_spec.rb +83 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/json_serializer_spec.rb +32 -1
- data/spec/extensions/migration_spec.rb +28 -0
- data/spec/extensions/nested_attributes_spec.rb +134 -1
- data/spec/extensions/optimistic_locking_spec.rb +15 -1
- data/spec/extensions/pg_hstore_spec.rb +1 -1
- data/spec/extensions/pg_inet_spec.rb +44 -0
- data/spec/extensions/pg_json_spec.rb +101 -0
- data/spec/extensions/prepared_statements_spec.rb +30 -0
- data/spec/extensions/rcte_tree_spec.rb +9 -0
- data/spec/extensions/schema_dumper_spec.rb +195 -7
- data/spec/extensions/serialization_spec.rb +4 -0
- data/spec/extensions/spec_helper.rb +9 -1
- data/spec/extensions/tactical_eager_loading_spec.rb +8 -0
- data/spec/integration/database_test.rb +5 -1
- data/spec/integration/prepared_statement_test.rb +20 -2
- data/spec/model/associations_spec.rb +27 -0
- data/spec/model/base_spec.rb +54 -0
- data/spec/model/model_spec.rb +6 -0
- data/spec/model/record_spec.rb +18 -0
- data/spec/rcov.opts +2 -0
- metadata +14 -3
@@ -13,6 +13,7 @@ describe "An SQLite database" do
|
|
13
13
|
end
|
14
14
|
after do
|
15
15
|
@db.foreign_keys = @fk
|
16
|
+
@db.case_sensitive_like = true
|
16
17
|
Sequel.datetime_class = Time
|
17
18
|
end
|
18
19
|
|
@@ -38,6 +39,16 @@ describe "An SQLite database" do
|
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
42
|
+
specify "should respect case sensitive like false" do
|
43
|
+
@db.case_sensitive_like = false
|
44
|
+
@db.get(Sequel.like('a', 'A')).to_s.should == '1'
|
45
|
+
end
|
46
|
+
|
47
|
+
specify "should respect case sensitive like true" do
|
48
|
+
@db.case_sensitive_like = true
|
49
|
+
@db.get(Sequel.like('a', 'A')).to_s.should == '0'
|
50
|
+
end
|
51
|
+
|
41
52
|
specify "should provide the SQLite version as an integer" do
|
42
53
|
@db.sqlite_version.should be_a_kind_of(Integer)
|
43
54
|
end
|
@@ -187,7 +187,7 @@ describe "A connection pool with a max size of 1" do
|
|
187
187
|
q.push nil
|
188
188
|
q1.pop
|
189
189
|
|
190
|
-
t1.
|
190
|
+
t1.join
|
191
191
|
t2.should be_alive
|
192
192
|
|
193
193
|
c2.should == 'hello'
|
@@ -340,6 +340,31 @@ shared_examples_for "A threaded connection pool" do
|
|
340
340
|
@pool.available_connections.size.should == 5
|
341
341
|
@pool.allocated.should be_empty
|
342
342
|
end
|
343
|
+
|
344
|
+
specify "should store connections in a stack by default" do
|
345
|
+
c2 = nil
|
346
|
+
c = @pool.hold{|cc| Thread.new{@pool.hold{|cc2| c2 = cc2}}.join; cc}
|
347
|
+
@pool.size.should == 2
|
348
|
+
@pool.hold{|cc| cc.should == c}
|
349
|
+
@pool.hold{|cc| cc.should == c}
|
350
|
+
@pool.hold do |cc|
|
351
|
+
cc.should == c
|
352
|
+
Thread.new{@pool.hold{|cc2| cc2.should == c2}}
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
specify "should store connections in a queue if :connection_handling=>:queue" do
|
357
|
+
@pool = Sequel::ConnectionPool.get_pool(@cp_opts.merge(:connection_handling=>:queue)){@invoked_count += 1}
|
358
|
+
c2 = nil
|
359
|
+
c = @pool.hold{|cc| Thread.new{@pool.hold{|cc2| c2 = cc2}}.join; cc}
|
360
|
+
@pool.size.should == 2
|
361
|
+
@pool.hold{|cc| cc.should == c2}
|
362
|
+
@pool.hold{|cc| cc.should == c}
|
363
|
+
@pool.hold do |cc|
|
364
|
+
cc.should == c2
|
365
|
+
Thread.new{@pool.hold{|cc2| cc2.should == c}}
|
366
|
+
end
|
367
|
+
end
|
343
368
|
end
|
344
369
|
|
345
370
|
describe "Threaded Unsharded Connection Pool" do
|
data/spec/core/database_spec.rb
CHANGED
@@ -1996,12 +1996,31 @@ describe "Database#supports_transactional_ddl?" do
|
|
1996
1996
|
end
|
1997
1997
|
end
|
1998
1998
|
|
1999
|
+
describe "Database#global_index_namespace?" do
|
2000
|
+
specify "should be true by default" do
|
2001
|
+
Sequel::Database.new.global_index_namespace?.should == true
|
2002
|
+
end
|
2003
|
+
end
|
2004
|
+
|
1999
2005
|
describe "Database#supports_savepoints?" do
|
2000
2006
|
specify "should be false by default" do
|
2001
2007
|
Sequel::Database.new.supports_savepoints?.should == false
|
2002
2008
|
end
|
2003
2009
|
end
|
2004
2010
|
|
2011
|
+
describe "Database#supports_savepoints_in_prepared_transactions?" do
|
2012
|
+
specify "should be false by default" do
|
2013
|
+
Sequel::Database.new.supports_savepoints_in_prepared_transactions?.should == false
|
2014
|
+
end
|
2015
|
+
|
2016
|
+
specify "should be true if both savepoints and prepared transactions are supported" do
|
2017
|
+
db = Sequel::Database.new
|
2018
|
+
db.meta_def(:supports_savepoints?){true}
|
2019
|
+
db.meta_def(:supports_prepared_transactions?){true}
|
2020
|
+
db.supports_savepoints_in_prepared_transactions?.should == true
|
2021
|
+
end
|
2022
|
+
end
|
2023
|
+
|
2005
2024
|
describe "Database#supports_prepared_transactions?" do
|
2006
2025
|
specify "should be false by default" do
|
2007
2026
|
Sequel::Database.new.supports_prepared_transactions?.should == false
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -1199,6 +1199,17 @@ describe "Dataset#from" do
|
|
1199
1199
|
@dataset.from(@dataset.from(:a)).select_sql.should == "SELECT * FROM (SELECT * FROM a) AS t1"
|
1200
1200
|
end
|
1201
1201
|
|
1202
|
+
specify "should treat string arguments as identifiers" do
|
1203
|
+
@dataset.quote_identifiers = true
|
1204
|
+
@dataset.from('a').select_sql.should == "SELECT * FROM \"a\""
|
1205
|
+
end
|
1206
|
+
|
1207
|
+
specify "should not treat literal strings or blobs as identifiers" do
|
1208
|
+
@dataset.quote_identifiers = true
|
1209
|
+
@dataset.from('a'.lit).select_sql.should == "SELECT * FROM a"
|
1210
|
+
@dataset.from('a'.to_sequel_blob).select_sql.should == "SELECT * FROM 'a'"
|
1211
|
+
end
|
1212
|
+
|
1202
1213
|
specify "should remove all FROM tables if called with no arguments" do
|
1203
1214
|
@dataset.from.sql.should == 'SELECT *'
|
1204
1215
|
end
|
@@ -1262,6 +1273,10 @@ describe "Dataset#select" do
|
|
1262
1273
|
@d.select.sql.should == 'SELECT * FROM test'
|
1263
1274
|
end
|
1264
1275
|
|
1276
|
+
specify "should handle array condition specifiers that are aliased" do
|
1277
|
+
@d.select(Sequel.as([[:b, :c]], :n)).sql.should == 'SELECT (b = c) AS n FROM test'
|
1278
|
+
end
|
1279
|
+
|
1265
1280
|
specify "should accept a hash for AS values" do
|
1266
1281
|
@d.select(:name => 'n', :__ggh => 'age').sql.should =~ /SELECT ((name AS n, __ggh AS age)|(__ggh AS age, name AS n)) FROM test/
|
1267
1282
|
end
|
@@ -2647,6 +2662,11 @@ describe "Dataset#get" do
|
|
2647
2662
|
specify "should raise an error if both a regular argument and block argument are used" do
|
2648
2663
|
proc{@d.get(:name){|o| o.x__b.as(:name)}}.should raise_error(Sequel::Error)
|
2649
2664
|
end
|
2665
|
+
|
2666
|
+
specify "should support false and nil values" do
|
2667
|
+
@d.get(false).should == "SELECT 'f' FROM test LIMIT 1"
|
2668
|
+
@d.get(nil).should == "SELECT NULL FROM test LIMIT 1"
|
2669
|
+
end
|
2650
2670
|
end
|
2651
2671
|
|
2652
2672
|
describe "Dataset#set_row_proc" do
|
@@ -3238,6 +3258,7 @@ describe "Dataset prepared statements and bound variables " do
|
|
3238
3258
|
end
|
3239
3259
|
|
3240
3260
|
specify "#call should take a type and bind hash and interpolate it" do
|
3261
|
+
@ds.filter(:num=>:$n).call(:each, :n=>1)
|
3241
3262
|
@ds.filter(:num=>:$n).call(:select, :n=>1)
|
3242
3263
|
@ds.filter(:num=>:$n).call([:map, :a], :n=>1)
|
3243
3264
|
@ds.filter(:num=>:$n).call([:to_hash, :a, :b], :n=>1)
|
@@ -3247,7 +3268,9 @@ describe "Dataset prepared statements and bound variables " do
|
|
3247
3268
|
@ds.filter(:num=>:$n).call(:update, {:n=>1, :n2=>2}, :num=>:$n2)
|
3248
3269
|
@ds.call(:insert, {:n=>1}, :num=>:$n)
|
3249
3270
|
@ds.call(:insert_select, {:n=>1}, :num=>:$n)
|
3250
|
-
@db.sqls.should == [
|
3271
|
+
@db.sqls.should == [
|
3272
|
+
'SELECT * FROM items WHERE (num = 1)',
|
3273
|
+
'SELECT * FROM items WHERE (num = 1)',
|
3251
3274
|
'SELECT * FROM items WHERE (num = 1)',
|
3252
3275
|
'SELECT * FROM items WHERE (num = 1)',
|
3253
3276
|
'SELECT * FROM items WHERE (num = 1)',
|
@@ -3260,6 +3283,7 @@ describe "Dataset prepared statements and bound variables " do
|
|
3260
3283
|
|
3261
3284
|
specify "#prepare should take a type and name and store it in the database for later use with call" do
|
3262
3285
|
pss = []
|
3286
|
+
pss << @ds.filter(:num=>:$n).prepare(:each, :en)
|
3263
3287
|
pss << @ds.filter(:num=>:$n).prepare(:select, :sn)
|
3264
3288
|
pss << @ds.filter(:num=>:$n).prepare([:map, :a], :sm)
|
3265
3289
|
pss << @ds.filter(:num=>:$n).prepare([:to_hash, :a, :b], :sh)
|
@@ -3269,8 +3293,9 @@ describe "Dataset prepared statements and bound variables " do
|
|
3269
3293
|
pss << @ds.filter(:num=>:$n).prepare(:update, :un, :num=>:$n2)
|
3270
3294
|
pss << @ds.prepare(:insert, :in, :num=>:$n)
|
3271
3295
|
pss << @ds.prepare(:insert_select, :ins, :num=>:$n)
|
3272
|
-
@db.prepared_statements.keys.sort_by{|k| k.to_s}.should == [:dn, :fn, :in, :ins, :sh, :shg, :sm, :sn, :un]
|
3273
|
-
[:sn, :sm, :sh, :shg, :fn, :dn, :un, :in, :ins].each_with_index{|x, i| @db.prepared_statements[x].should == pss[i]}
|
3296
|
+
@db.prepared_statements.keys.sort_by{|k| k.to_s}.should == [:dn, :en, :fn, :in, :ins, :sh, :shg, :sm, :sn, :un]
|
3297
|
+
[:en, :sn, :sm, :sh, :shg, :fn, :dn, :un, :in, :ins].each_with_index{|x, i| @db.prepared_statements[x].should == pss[i]}
|
3298
|
+
@db.call(:en, :n=>1){}
|
3274
3299
|
@db.call(:sn, :n=>1)
|
3275
3300
|
@db.call(:sm, :n=>1)
|
3276
3301
|
@db.call(:sh, :n=>1)
|
@@ -3280,7 +3305,9 @@ describe "Dataset prepared statements and bound variables " do
|
|
3280
3305
|
@db.call(:un, :n=>1, :n2=>2)
|
3281
3306
|
@db.call(:in, :n=>1)
|
3282
3307
|
@db.call(:ins, :n=>1)
|
3283
|
-
@db.sqls.should == [
|
3308
|
+
@db.sqls.should == [
|
3309
|
+
'SELECT * FROM items WHERE (num = 1)',
|
3310
|
+
'SELECT * FROM items WHERE (num = 1)',
|
3284
3311
|
'SELECT * FROM items WHERE (num = 1)',
|
3285
3312
|
'SELECT * FROM items WHERE (num = 1)',
|
3286
3313
|
'SELECT * FROM items WHERE (num = 1)',
|
@@ -3291,6 +3318,11 @@ describe "Dataset prepared statements and bound variables " do
|
|
3291
3318
|
'INSERT INTO items (num) VALUES (1) RETURNING *']
|
3292
3319
|
end
|
3293
3320
|
|
3321
|
+
specify "#call should default to using :all if an invalid type is given" do
|
3322
|
+
@ds.filter(:num=>:$n).call(:select_all, :n=>1)
|
3323
|
+
@db.sqls.should == ['SELECT * FROM items WHERE (num = 1)']
|
3324
|
+
end
|
3325
|
+
|
3294
3326
|
specify "#inspect should indicate it is a prepared statement with the prepared SQL" do
|
3295
3327
|
@ds.filter(:num=>:$n).prepare(:select, :sn).inspect.should == \
|
3296
3328
|
'<Sequel::Mock::Dataset/PreparedStatement "SELECT * FROM items WHERE (num = $n)">'
|
@@ -3361,7 +3393,7 @@ describe Sequel::Dataset::UnnumberedArgumentMapper do
|
|
3361
3393
|
@ps.first.inspect.should == '<Sequel::Mock::Dataset/PreparedStatement "SELECT * FROM items WHERE (num = ?)">'
|
3362
3394
|
end
|
3363
3395
|
|
3364
|
-
specify "should
|
3396
|
+
specify "should submit the SQL to the database with placeholders and bind variables" do
|
3365
3397
|
@ps.each{|p| p.prepared_sql; p.call(:n=>1)}
|
3366
3398
|
@db.sqls.should == ["SELECT * FROM items WHERE (num = ?) -- args: [1]",
|
3367
3399
|
"SELECT * FROM items WHERE (num = ?) -- args: [1]",
|
@@ -3370,6 +3402,14 @@ describe Sequel::Dataset::UnnumberedArgumentMapper do
|
|
3370
3402
|
"INSERT INTO items (num) VALUES (?) -- args: [1]",
|
3371
3403
|
"UPDATE items SET num = ? WHERE (num = ?) -- args: [1, 1]"]
|
3372
3404
|
end
|
3405
|
+
|
3406
|
+
specify "should handle unrecognized statement types as :all" do
|
3407
|
+
ps = @ds.prepare(:select_all, :s)
|
3408
|
+
ps.extend(Sequel::Dataset::UnnumberedArgumentMapper)
|
3409
|
+
ps.prepared_sql
|
3410
|
+
ps.call(:n=>1)
|
3411
|
+
@db.sqls.should == ["SELECT * FROM items WHERE (num = ?) -- args: [1]"]
|
3412
|
+
end
|
3373
3413
|
end
|
3374
3414
|
|
3375
3415
|
describe "Sequel::Dataset#server" do
|
@@ -212,8 +212,6 @@ describe "Blockless Ruby Filters" do
|
|
212
212
|
@d.l(:x.sql_boolean & :y).should == '(x AND y)'
|
213
213
|
@d.l(:x & :y & :z).should == '(x AND y AND z)'
|
214
214
|
@d.l(:x & {:y => :z}).should == '(x AND (y = z))'
|
215
|
-
@d.l({:y => :z} & :x).should == '((y = z) AND x)'
|
216
|
-
@d.l({:x => :a} & {:y => :z}).should == '((x = a) AND (y = z))'
|
217
215
|
@d.l((:x + 200 < 0) & (:y - 200 < 0)).should == '(((x + 200) < 0) AND ((y - 200) < 0))'
|
218
216
|
@d.l(:x & ~:y).should == '(x AND NOT y)'
|
219
217
|
@d.l(~:x & :y).should == '(NOT x AND y)'
|
@@ -225,8 +223,6 @@ describe "Blockless Ruby Filters" do
|
|
225
223
|
@d.l(:x.sql_boolean | :y).should == '(x OR y)'
|
226
224
|
@d.l(:x | :y | :z).should == '(x OR y OR z)'
|
227
225
|
@d.l(:x | {:y => :z}).should == '(x OR (y = z))'
|
228
|
-
@d.l({:y => :z} | :x).should == '((y = z) OR x)'
|
229
|
-
@d.l({:x => :a} | {:y => :z}).should == '((x = a) OR (y = z))'
|
230
226
|
@d.l((:x.sql_number > 200) | (:y.sql_number < 200)).should == '((x > 200) OR (y < 200))'
|
231
227
|
end
|
232
228
|
|
@@ -267,60 +263,12 @@ describe "Blockless Ruby Filters" do
|
|
267
263
|
@d.l(:x => nil, :y => [1,2,3])[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
|
268
264
|
end
|
269
265
|
|
270
|
-
it "should support sql_expr on hashes" do
|
271
|
-
@d.l({:x => 100, :y => 'a'}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x = 100)', '(y = \'a\')']
|
272
|
-
@d.l({:x => true, :y => false}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
|
273
|
-
@d.l({:x => nil, :y => [1,2,3]}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
|
274
|
-
end
|
275
|
-
|
276
|
-
it "should support sql_negate on hashes" do
|
277
|
-
@d.l({:x => 100, :y => 'a'}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x != 100)', '(y != \'a\')']
|
278
|
-
@d.l({:x => true, :y => false}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
|
279
|
-
@d.l({:x => nil, :y => [1,2,3]}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
|
280
|
-
end
|
281
|
-
|
282
|
-
it "should support ~ on hashes" do
|
283
|
-
@d.l(~{:x => 100, :y => 'a'})[1...-1].split(' OR ').sort.should == ['(x != 100)', '(y != \'a\')']
|
284
|
-
@d.l(~{:x => true, :y => false})[1...-1].split(' OR ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
|
285
|
-
@d.l(~{:x => nil, :y => [1,2,3]})[1...-1].split(' OR ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
|
286
|
-
end
|
287
|
-
|
288
|
-
it "should support sql_or on hashes" do
|
289
|
-
@d.l({:x => 100, :y => 'a'}.sql_or)[1...-1].split(' OR ').sort.should == ['(x = 100)', '(y = \'a\')']
|
290
|
-
@d.l({:x => true, :y => false}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
|
291
|
-
@d.l({:x => nil, :y => [1,2,3]}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
|
292
|
-
end
|
293
|
-
|
294
266
|
it "should support arrays with all two pairs the same as hashes" do
|
295
267
|
@d.l([[:x, 100],[:y, 'a']]).should == '((x = 100) AND (y = \'a\'))'
|
296
268
|
@d.l([[:x, true], [:y, false]]).should == '((x IS TRUE) AND (y IS FALSE))'
|
297
269
|
@d.l([[:x, nil], [:y, [1,2,3]]]).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
|
298
270
|
end
|
299
271
|
|
300
|
-
it "should support sql_expr on arrays with all two pairs" do
|
301
|
-
@d.l([[:x, 100],[:y, 'a']].sql_expr).should == '((x = 100) AND (y = \'a\'))'
|
302
|
-
@d.l([[:x, true], [:y, false]].sql_expr).should == '((x IS TRUE) AND (y IS FALSE))'
|
303
|
-
@d.l([[:x, nil], [:y, [1,2,3]]].sql_expr).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
|
304
|
-
end
|
305
|
-
|
306
|
-
it "should support sql_negate on arrays with all two pairs" do
|
307
|
-
@d.l([[:x, 100],[:y, 'a']].sql_negate).should == '((x != 100) AND (y != \'a\'))'
|
308
|
-
@d.l([[:x, true], [:y, false]].sql_negate).should == '((x IS NOT TRUE) AND (y IS NOT FALSE))'
|
309
|
-
@d.l([[:x, nil], [:y, [1,2,3]]].sql_negate).should == '((x IS NOT NULL) AND (y NOT IN (1, 2, 3)))'
|
310
|
-
end
|
311
|
-
|
312
|
-
it "should support ~ on arrays with all two pairs" do
|
313
|
-
@d.l(~[[:x, 100],[:y, 'a']]).should == '((x != 100) OR (y != \'a\'))'
|
314
|
-
@d.l(~[[:x, true], [:y, false]]).should == '((x IS NOT TRUE) OR (y IS NOT FALSE))'
|
315
|
-
@d.l(~[[:x, nil], [:y, [1,2,3]]]).should == '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
|
316
|
-
end
|
317
|
-
|
318
|
-
it "should support sql_or on arrays with all two pairs" do
|
319
|
-
@d.l([[:x, 100],[:y, 'a']].sql_or).should == '((x = 100) OR (y = \'a\'))'
|
320
|
-
@d.l([[:x, true], [:y, false]].sql_or).should == '((x IS TRUE) OR (y IS FALSE))'
|
321
|
-
@d.l([[:x, nil], [:y, [1,2,3]]].sql_or).should == '((x IS NULL) OR (y IN (1, 2, 3)))'
|
322
|
-
end
|
323
|
-
|
324
272
|
it "should emulate columns for array values" do
|
325
273
|
@d.l([:x, :y]=>[[1,2], [3,4]].sql_array).should == '((x, y) IN ((1, 2), (3, 4)))'
|
326
274
|
@d.l([:x, :y, :z]=>[[1,2,5], [3,4,6]]).should == '((x, y, z) IN ((1, 2, 5), (3, 4, 6)))'
|
@@ -332,21 +280,6 @@ describe "Blockless Ruby Filters" do
|
|
332
280
|
@d.l([:x, :y, :z]=>[[1,2,5], [3,4,6]]).should == '(((x = 1) AND (y = 2) AND (z = 5)) OR ((x = 3) AND (y = 4) AND (z = 6)))'
|
333
281
|
end
|
334
282
|
|
335
|
-
it "should support Array#sql_string_join for concatenation of SQL strings" do
|
336
|
-
@d.lit([:x].sql_string_join).should == '(x)'
|
337
|
-
@d.lit([:x].sql_string_join(', ')).should == '(x)'
|
338
|
-
@d.lit([:x, :y].sql_string_join).should == '(x || y)'
|
339
|
-
@d.lit([:x, :y].sql_string_join(', ')).should == "(x || ', ' || y)"
|
340
|
-
@d.lit([:x.sql_function(1), :y.sql_subscript(1)].sql_string_join).should == '(x(1) || y[1])'
|
341
|
-
@d.lit([:x.sql_function(1), 'y.z'.lit].sql_string_join(', ')).should == "(x(1) || ', ' || y.z)"
|
342
|
-
@d.lit([:x, 1, :y].sql_string_join).should == "(x || '1' || y)"
|
343
|
-
@d.lit([:x, 1, :y].sql_string_join(', ')).should == "(x || ', ' || '1' || ', ' || y)"
|
344
|
-
@d.lit([:x, 1, :y].sql_string_join(:y__z)).should == "(x || y.z || '1' || y.z || y)"
|
345
|
-
@d.lit([:x, 1, :y].sql_string_join(1)).should == "(x || '1' || '1' || '1' || y)"
|
346
|
-
@d.lit([:x, :y].sql_string_join('y.x || x.y'.lit)).should == "(x || y.x || x.y || y)"
|
347
|
-
@d.lit([[:x, :y].sql_string_join, [:a, :b].sql_string_join].sql_string_join).should == "(x || y || a || b)"
|
348
|
-
end
|
349
|
-
|
350
283
|
it "should support StringExpression#+ for concatenation of SQL strings" do
|
351
284
|
@d.lit(:x.sql_string + :y).should == '(x || y)'
|
352
285
|
@d.lit([:x].sql_string_join + :y).should == '(x || y)'
|
@@ -762,6 +695,11 @@ describe "Sequel core extension replacements" do
|
|
762
695
|
l(Sequel.expr([[:a, 1], [:b, 2]]) & nil, "((a = 1) AND (b = 2) AND NULL)")
|
763
696
|
end
|
764
697
|
|
698
|
+
it "Sequel.expr should handle arrays that are not condition specifiers" do
|
699
|
+
l(Sequel.expr([1]), "(1)")
|
700
|
+
l(Sequel.expr([1, 2]), "(1, 2)")
|
701
|
+
end
|
702
|
+
|
765
703
|
it "Sequel.expr should treat blocks/procs as virtual rows and wrap the output" do
|
766
704
|
l(Sequel.expr{1} + 1, "(1 + 1)")
|
767
705
|
l(Sequel.expr{o__a} + 1, "(o.a + 1)")
|
@@ -1078,3 +1016,29 @@ describe "Sequel::SQL::Wrapper" do
|
|
1078
1016
|
@ds.literal(s.sql_string + '1').should == "(foo || '1')"
|
1079
1017
|
end
|
1080
1018
|
end
|
1019
|
+
|
1020
|
+
describe "Sequel::SQL::Blob#to_sequel_blob" do
|
1021
|
+
specify "should return self" do
|
1022
|
+
c = Sequel::SQL::Blob.new('a')
|
1023
|
+
c.to_sequel_blob.should equal(c)
|
1024
|
+
end
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
describe Sequel::SQL::Subscript do
|
1028
|
+
before do
|
1029
|
+
@s = Sequel::SQL::Subscript.new(:a, [1])
|
1030
|
+
@ds = Sequel::Dataset.new(nil)
|
1031
|
+
end
|
1032
|
+
|
1033
|
+
specify "should have | return a new non-nested subscript" do
|
1034
|
+
s = (@s | 2)
|
1035
|
+
s.should_not equal(@s)
|
1036
|
+
@ds.literal(s).should == 'a[1, 2]'
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
specify "should have [] return a new nested subscript" do
|
1040
|
+
s = @s[2]
|
1041
|
+
s.should_not equal(@s)
|
1042
|
+
@ds.literal(s).should == 'a[1][2]'
|
1043
|
+
end
|
1044
|
+
end
|
@@ -442,4 +442,8 @@ describe "Sequel Mock Adapter" do
|
|
442
442
|
specify "should automatically set version for postgres" do
|
443
443
|
Sequel.mock(:host=>'postgres').server_version.should == 90103
|
444
444
|
end
|
445
|
+
|
446
|
+
specify "should stub out the primary_key method for postgres" do
|
447
|
+
Sequel.mock(:host=>'postgres').primary_key(:t).should == :id
|
448
|
+
end
|
445
449
|
end
|
@@ -18,6 +18,89 @@ describe "Sequel core extensions" do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
describe "Array and Hash extensions" do
|
22
|
+
before do
|
23
|
+
db = Sequel::Database.new
|
24
|
+
@d = db[:items]
|
25
|
+
def @d.l(*args, &block)
|
26
|
+
literal(filter_expr(*args, &block))
|
27
|
+
end
|
28
|
+
def @d.lit(*args)
|
29
|
+
literal(*args)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should support sql_expr on arrays with all two pairs" do
|
34
|
+
@d.l([[:x, 100],[:y, 'a']].sql_expr).should == '((x = 100) AND (y = \'a\'))'
|
35
|
+
@d.l([[:x, true], [:y, false]].sql_expr).should == '((x IS TRUE) AND (y IS FALSE))'
|
36
|
+
@d.l([[:x, nil], [:y, [1,2,3]]].sql_expr).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should support sql_negate on arrays with all two pairs" do
|
40
|
+
@d.l([[:x, 100],[:y, 'a']].sql_negate).should == '((x != 100) AND (y != \'a\'))'
|
41
|
+
@d.l([[:x, true], [:y, false]].sql_negate).should == '((x IS NOT TRUE) AND (y IS NOT FALSE))'
|
42
|
+
@d.l([[:x, nil], [:y, [1,2,3]]].sql_negate).should == '((x IS NOT NULL) AND (y NOT IN (1, 2, 3)))'
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should support ~ on arrays with all two pairs" do
|
46
|
+
@d.l(~[[:x, 100],[:y, 'a']]).should == '((x != 100) OR (y != \'a\'))'
|
47
|
+
@d.l(~[[:x, true], [:y, false]]).should == '((x IS NOT TRUE) OR (y IS NOT FALSE))'
|
48
|
+
@d.l(~[[:x, nil], [:y, [1,2,3]]]).should == '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should support sql_or on arrays with all two pairs" do
|
52
|
+
@d.l([[:x, 100],[:y, 'a']].sql_or).should == '((x = 100) OR (y = \'a\'))'
|
53
|
+
@d.l([[:x, true], [:y, false]].sql_or).should == '((x IS TRUE) OR (y IS FALSE))'
|
54
|
+
@d.l([[:x, nil], [:y, [1,2,3]]].sql_or).should == '((x IS NULL) OR (y IN (1, 2, 3)))'
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should support Array#sql_string_join for concatenation of SQL strings" do
|
58
|
+
@d.lit([:x].sql_string_join).should == '(x)'
|
59
|
+
@d.lit([:x].sql_string_join(', ')).should == '(x)'
|
60
|
+
@d.lit([:x, :y].sql_string_join).should == '(x || y)'
|
61
|
+
@d.lit([:x, :y].sql_string_join(', ')).should == "(x || ', ' || y)"
|
62
|
+
@d.lit([:x.sql_function(1), :y.sql_subscript(1)].sql_string_join).should == '(x(1) || y[1])'
|
63
|
+
@d.lit([:x.sql_function(1), 'y.z'.lit].sql_string_join(', ')).should == "(x(1) || ', ' || y.z)"
|
64
|
+
@d.lit([:x, 1, :y].sql_string_join).should == "(x || '1' || y)"
|
65
|
+
@d.lit([:x, 1, :y].sql_string_join(', ')).should == "(x || ', ' || '1' || ', ' || y)"
|
66
|
+
@d.lit([:x, 1, :y].sql_string_join(:y__z)).should == "(x || y.z || '1' || y.z || y)"
|
67
|
+
@d.lit([:x, 1, :y].sql_string_join(1)).should == "(x || '1' || '1' || '1' || y)"
|
68
|
+
@d.lit([:x, :y].sql_string_join('y.x || x.y'.lit)).should == "(x || y.x || x.y || y)"
|
69
|
+
@d.lit([[:x, :y].sql_string_join, [:a, :b].sql_string_join].sql_string_join).should == "(x || y || a || b)"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should support sql_expr on hashes" do
|
73
|
+
@d.l({:x => 100, :y => 'a'}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x = 100)', '(y = \'a\')']
|
74
|
+
@d.l({:x => true, :y => false}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
|
75
|
+
@d.l({:x => nil, :y => [1,2,3]}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should support sql_negate on hashes" do
|
79
|
+
@d.l({:x => 100, :y => 'a'}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x != 100)', '(y != \'a\')']
|
80
|
+
@d.l({:x => true, :y => false}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
|
81
|
+
@d.l({:x => nil, :y => [1,2,3]}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should support ~ on hashes" do
|
85
|
+
@d.l(~{:x => 100, :y => 'a'})[1...-1].split(' OR ').sort.should == ['(x != 100)', '(y != \'a\')']
|
86
|
+
@d.l(~{:x => true, :y => false})[1...-1].split(' OR ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
|
87
|
+
@d.l(~{:x => nil, :y => [1,2,3]})[1...-1].split(' OR ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should support sql_or on hashes" do
|
91
|
+
@d.l({:x => 100, :y => 'a'}.sql_or)[1...-1].split(' OR ').sort.should == ['(x = 100)', '(y = \'a\')']
|
92
|
+
@d.l({:x => true, :y => false}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
|
93
|
+
@d.l({:x => nil, :y => [1,2,3]}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should Hash#& and Hash#|" do
|
97
|
+
@d.l({:y => :z} & :x).should == '((y = z) AND x)'
|
98
|
+
@d.l({:x => :a} & {:y => :z}).should == '((x = a) AND (y = z))'
|
99
|
+
@d.l({:y => :z} | :x).should == '((y = z) OR x)'
|
100
|
+
@d.l({:x => :a} | {:y => :z}).should == '((x = a) OR (y = z))'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
21
104
|
describe "Array#case and Hash#case" do
|
22
105
|
before do
|
23
106
|
@d = Sequel::Dataset.new(nil)
|