sequel 3.40.0 → 3.41.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 +40 -0
- data/README.rdoc +2 -2
- data/doc/advanced_associations.rdoc +12 -0
- data/doc/bin_sequel.rdoc +144 -0
- data/doc/migration.rdoc +1 -1
- data/doc/object_model.rdoc +29 -0
- data/doc/release_notes/3.41.0.txt +155 -0
- data/lib/sequel/adapters/ado.rb +4 -4
- data/lib/sequel/adapters/amalgalite.rb +0 -5
- data/lib/sequel/adapters/cubrid.rb +2 -2
- data/lib/sequel/adapters/db2.rb +9 -5
- data/lib/sequel/adapters/dbi.rb +4 -6
- data/lib/sequel/adapters/do.rb +4 -5
- data/lib/sequel/adapters/firebird.rb +8 -4
- data/lib/sequel/adapters/ibmdb.rb +2 -3
- data/lib/sequel/adapters/informix.rb +0 -6
- data/lib/sequel/adapters/jdbc.rb +11 -7
- data/lib/sequel/adapters/jdbc/db2.rb +22 -0
- data/lib/sequel/adapters/jdbc/derby.rb +5 -5
- data/lib/sequel/adapters/jdbc/h2.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +1 -1
- data/lib/sequel/adapters/jdbc/sqlserver.rb +6 -0
- data/lib/sequel/adapters/mock.rb +3 -3
- data/lib/sequel/adapters/mysql.rb +7 -7
- data/lib/sequel/adapters/mysql2.rb +0 -5
- data/lib/sequel/adapters/odbc.rb +4 -4
- data/lib/sequel/adapters/openbase.rb +4 -6
- data/lib/sequel/adapters/oracle.rb +14 -6
- data/lib/sequel/adapters/postgres.rb +12 -8
- data/lib/sequel/adapters/shared/db2.rb +5 -0
- data/lib/sequel/adapters/shared/firebird.rb +10 -0
- data/lib/sequel/adapters/shared/mssql.rb +43 -1
- data/lib/sequel/adapters/shared/mysql.rb +1 -0
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +12 -0
- data/lib/sequel/adapters/shared/sqlite.rb +32 -0
- data/lib/sequel/adapters/sqlite.rb +9 -8
- data/lib/sequel/adapters/swift.rb +3 -8
- data/lib/sequel/adapters/tinytds.rb +5 -5
- data/lib/sequel/connection_pool.rb +13 -19
- data/lib/sequel/connection_pool/sharded_single.rb +12 -12
- data/lib/sequel/connection_pool/sharded_threaded.rb +37 -17
- data/lib/sequel/connection_pool/single.rb +6 -3
- data/lib/sequel/connection_pool/threaded.rb +33 -13
- data/lib/sequel/database/connecting.rb +28 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +2 -5
- data/lib/sequel/database/query.rb +2 -2
- data/lib/sequel/database/schema_generator.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +3 -0
- data/lib/sequel/dataset/query.rb +8 -4
- data/lib/sequel/dataset/sql.rb +7 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +1 -1
- data/lib/sequel/extensions/connection_validator.rb +109 -0
- data/lib/sequel/extensions/pg_array.rb +2 -0
- data/lib/sequel/extensions/pg_hstore.rb +2 -0
- data/lib/sequel/extensions/pg_json.rb +4 -0
- data/lib/sequel/extensions/pg_range.rb +1 -0
- data/lib/sequel/extensions/pg_row.rb +4 -0
- data/lib/sequel/plugins/prepared_statements.rb +2 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +53 -10
- data/lib/sequel/plugins/touch.rb +18 -6
- data/lib/sequel/plugins/validation_class_methods.rb +1 -0
- data/lib/sequel/plugins/validation_helpers.rb +3 -1
- data/lib/sequel/sql.rb +61 -19
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/firebird_spec.rb +52 -38
- data/spec/adapters/mssql_spec.rb +67 -0
- data/spec/adapters/mysql_spec.rb +192 -116
- data/spec/adapters/postgres_spec.rb +133 -70
- data/spec/adapters/spec_helper.rb +7 -0
- data/spec/adapters/sqlite_spec.rb +34 -1
- data/spec/core/connection_pool_spec.rb +79 -75
- data/spec/core/database_spec.rb +9 -4
- data/spec/core/dataset_spec.rb +15 -0
- data/spec/core/expression_filters_spec.rb +40 -2
- data/spec/extensions/connection_validator_spec.rb +118 -0
- data/spec/extensions/pg_array_spec.rb +4 -0
- data/spec/extensions/single_table_inheritance_spec.rb +42 -0
- data/spec/extensions/touch_spec.rb +40 -0
- data/spec/extensions/validation_class_methods_spec.rb +19 -1
- data/spec/extensions/validation_helpers_spec.rb +17 -0
- data/spec/integration/database_test.rb +14 -0
- data/spec/integration/dataset_test.rb +3 -3
- data/spec/integration/plugin_test.rb +41 -12
- data/spec/integration/schema_test.rb +14 -0
- data/spec/integration/spec_helper.rb +7 -0
- data/spec/integration/type_test.rb +3 -0
- metadata +9 -3
data/spec/core/database_spec.rb
CHANGED
@@ -37,7 +37,8 @@ describe "A new Database" do
|
|
37
37
|
|
38
38
|
specify "should pass the supplied block to the connection pool" do
|
39
39
|
cc = nil
|
40
|
-
d = Sequel::Database.new
|
40
|
+
d = Sequel::Database.new
|
41
|
+
d.meta_def(:connect){|c| 1234}
|
41
42
|
d.synchronize {|c| cc = c}
|
42
43
|
cc.should == 1234
|
43
44
|
end
|
@@ -538,7 +539,8 @@ end
|
|
538
539
|
|
539
540
|
describe "Database#synchronize" do
|
540
541
|
before do
|
541
|
-
@db = Sequel::Database.new(:max_connections => 1)
|
542
|
+
@db = Sequel::Database.new(:max_connections => 1)
|
543
|
+
@db.meta_def(:connect){|c| 12345}
|
542
544
|
end
|
543
545
|
|
544
546
|
specify "should wrap the supplied block in pool.hold" do
|
@@ -561,7 +563,9 @@ end
|
|
561
563
|
|
562
564
|
describe "Database#test_connection" do
|
563
565
|
before do
|
564
|
-
@db = Sequel::Database.new
|
566
|
+
@db = Sequel::Database.new
|
567
|
+
pr = proc{@test = rand(100)}
|
568
|
+
@db.meta_def(:connect){|c| pr.call}
|
565
569
|
end
|
566
570
|
|
567
571
|
specify "should attempt to get a connection" do
|
@@ -1258,7 +1262,8 @@ end
|
|
1258
1262
|
describe "A single threaded database" do
|
1259
1263
|
before do
|
1260
1264
|
conn = 1234567
|
1261
|
-
@db = Sequel::Database.new(:single_threaded => true)
|
1265
|
+
@db = Sequel::Database.new(:single_threaded => true)
|
1266
|
+
@db.meta_def(:connect) do |c|
|
1262
1267
|
conn += 1
|
1263
1268
|
end
|
1264
1269
|
end
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -1588,6 +1588,15 @@ describe "Dataset#reverse_order" do
|
|
1588
1588
|
specify "should have #reverse alias" do
|
1589
1589
|
@dataset.order(:name).reverse.sql.should == 'SELECT * FROM test ORDER BY name DESC'
|
1590
1590
|
end
|
1591
|
+
|
1592
|
+
specify "should accept a block" do
|
1593
|
+
@dataset.reverse{name}.sql.should == 'SELECT * FROM test ORDER BY name DESC'
|
1594
|
+
@dataset.reverse_order{name}.sql.should == 'SELECT * FROM test ORDER BY name DESC'
|
1595
|
+
@dataset.reverse(:foo){name}.sql.should == 'SELECT * FROM test ORDER BY foo DESC, name DESC'
|
1596
|
+
@dataset.reverse_order(:foo){name}.sql.should == 'SELECT * FROM test ORDER BY foo DESC, name DESC'
|
1597
|
+
@dataset.reverse(Sequel.desc(:foo)){name}.sql.should == 'SELECT * FROM test ORDER BY foo ASC, name DESC'
|
1598
|
+
@dataset.reverse_order(Sequel.desc(:foo)){name}.sql.should == 'SELECT * FROM test ORDER BY foo ASC, name DESC'
|
1599
|
+
end
|
1591
1600
|
end
|
1592
1601
|
|
1593
1602
|
describe "Dataset#limit" do
|
@@ -1620,6 +1629,12 @@ describe "Dataset#limit" do
|
|
1620
1629
|
@dataset.limit(6, Sequel.function(:a) - 1).sql.should == 'SELECT * FROM test LIMIT 6 OFFSET (a() - 1)'
|
1621
1630
|
end
|
1622
1631
|
|
1632
|
+
specify "should be able to reset limit and offset with nil values" do
|
1633
|
+
@dataset.limit(6).limit(nil).sql.should == 'SELECT * FROM test'
|
1634
|
+
@dataset.limit(6, 1).limit(nil).sql.should == 'SELECT * FROM test OFFSET 1'
|
1635
|
+
@dataset.limit(6, 1).limit(nil, nil).sql.should == 'SELECT * FROM test'
|
1636
|
+
end
|
1637
|
+
|
1623
1638
|
specify "should work with fixed sql datasets" do
|
1624
1639
|
@dataset.opts[:sql] = 'select * from cccc'
|
1625
1640
|
@dataset.limit(6, 10).sql.should == 'SELECT * FROM (select * from cccc) AS t1 LIMIT 6 OFFSET 10'
|
@@ -551,8 +551,8 @@ describe "Sequel core extension replacements" do
|
|
551
551
|
Sequel.expr({1=>2}).should be_a_kind_of(Sequel::SQL::BooleanExpression)
|
552
552
|
Sequel.expr([[1, 2]]).should be_a_kind_of(Sequel::SQL::BooleanExpression)
|
553
553
|
Sequel.expr([1]).should be_a_kind_of(Sequel::SQL::Wrapper)
|
554
|
-
Sequel.expr{|o| o.should be_a_kind_of(Sequel::SQL::
|
555
|
-
Sequel.expr{
|
554
|
+
Sequel.expr{|o| o.a}.should be_a_kind_of(Sequel::SQL::Identifier)
|
555
|
+
Sequel.expr{a}.should be_a_kind_of(Sequel::SQL::Identifier)
|
556
556
|
Sequel.expr(:a).should be_a_kind_of(Sequel::SQL::Identifier)
|
557
557
|
Sequel.expr(:a__b).should be_a_kind_of(Sequel::SQL::QualifiedIdentifier)
|
558
558
|
Sequel.expr(:a___c).should be_a_kind_of(Sequel::SQL::AliasedExpression)
|
@@ -966,3 +966,41 @@ describe "Sequel.recursive_map" do
|
|
966
966
|
Sequel.recursive_map([[nil]], proc{|s| s.to_i}).should == [[nil]]
|
967
967
|
end
|
968
968
|
end
|
969
|
+
|
970
|
+
describe "Sequel.delay" do
|
971
|
+
before do
|
972
|
+
@o = Class.new do
|
973
|
+
def a
|
974
|
+
@a ||= 0
|
975
|
+
@a += 1
|
976
|
+
end
|
977
|
+
def _a
|
978
|
+
@a
|
979
|
+
end
|
980
|
+
|
981
|
+
attr_accessor :b
|
982
|
+
end.new
|
983
|
+
end
|
984
|
+
|
985
|
+
specify "should delay calling the block until literalization" do
|
986
|
+
ds = Sequel.mock[:b].where(:a=>Sequel.delay{@o.a})
|
987
|
+
@o._a.should be_nil
|
988
|
+
ds.sql.should == "SELECT * FROM b WHERE (a = 1)"
|
989
|
+
@o._a.should == 1
|
990
|
+
ds.sql.should == "SELECT * FROM b WHERE (a = 2)"
|
991
|
+
@o._a.should == 2
|
992
|
+
end
|
993
|
+
|
994
|
+
specify "should have the condition specifier handling respect delayed evaluations" do
|
995
|
+
ds = Sequel.mock[:b].where(:a=>Sequel.delay{@o.b})
|
996
|
+
ds.sql.should == "SELECT * FROM b WHERE (a IS NULL)"
|
997
|
+
@o.b = 1
|
998
|
+
ds.sql.should == "SELECT * FROM b WHERE (a = 1)"
|
999
|
+
@o.b = [1, 2]
|
1000
|
+
ds.sql.should == "SELECT * FROM b WHERE (a IN (1, 2))"
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
specify "should raise if called without a block" do
|
1004
|
+
proc{Sequel.delay}.should raise_error(Sequel::Error)
|
1005
|
+
end
|
1006
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
shared_examples_for "Sequel::ConnectionValidator" do
|
4
|
+
before do
|
5
|
+
@db.extend(Module.new do
|
6
|
+
def disconnect_connection(conn)
|
7
|
+
@sqls << 'disconnect'
|
8
|
+
end
|
9
|
+
def valid_connection?(conn)
|
10
|
+
super
|
11
|
+
conn.valid
|
12
|
+
end
|
13
|
+
def connect(server)
|
14
|
+
conn = super
|
15
|
+
conn.extend(Module.new do
|
16
|
+
attr_accessor :valid
|
17
|
+
end)
|
18
|
+
conn.valid = true
|
19
|
+
conn
|
20
|
+
end
|
21
|
+
end)
|
22
|
+
@db.extension(:connection_validator)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should still allow new connections" do
|
26
|
+
@db.synchronize{|c| c}.should be_a_kind_of(Sequel::Mock::Connection)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should only validate if connection idle longer than timeout" do
|
30
|
+
c1 = @db.synchronize{|c| c}
|
31
|
+
@db.sqls.should == []
|
32
|
+
@db.synchronize{|c| c}.should equal(c1)
|
33
|
+
@db.sqls.should == []
|
34
|
+
@db.pool.connection_validation_timeout = -1
|
35
|
+
@db.synchronize{|c| c}.should equal(c1)
|
36
|
+
@db.sqls.should == ['SELECT NULL']
|
37
|
+
@db.pool.connection_validation_timeout = 1
|
38
|
+
@db.synchronize{|c| c}.should equal(c1)
|
39
|
+
@db.sqls.should == []
|
40
|
+
@db.synchronize{|c| c}.should equal(c1)
|
41
|
+
@db.sqls.should == []
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should disconnect connection if not valid" do
|
45
|
+
c1 = @db.synchronize{|c| c}
|
46
|
+
@db.sqls.should == []
|
47
|
+
c1.valid = false
|
48
|
+
@db.pool.connection_validation_timeout = -1
|
49
|
+
c2 = @db.synchronize{|c| c}
|
50
|
+
@db.sqls.should == ['SELECT NULL', 'disconnect']
|
51
|
+
c2.should_not equal(c1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should disconnect multiple connections repeatedly if they are not valid" do
|
55
|
+
q, q1 = Queue.new, Queue.new
|
56
|
+
c1 = nil
|
57
|
+
c2 = nil
|
58
|
+
@db.pool.connection_validation_timeout = -1
|
59
|
+
@db.synchronize do |c|
|
60
|
+
Thread.new do
|
61
|
+
@db.synchronize do |cc|
|
62
|
+
c2 = cc
|
63
|
+
end
|
64
|
+
q1.pop
|
65
|
+
q.push nil
|
66
|
+
end
|
67
|
+
q1.push nil
|
68
|
+
q.pop
|
69
|
+
c1 = c
|
70
|
+
end
|
71
|
+
c1.valid = false
|
72
|
+
c2.valid = false
|
73
|
+
|
74
|
+
c3 = @db.synchronize{|c| c}
|
75
|
+
@db.sqls.should == ['SELECT NULL', 'disconnect', 'SELECT NULL', 'disconnect']
|
76
|
+
c3.should_not equal(c1)
|
77
|
+
c3.should_not equal(c2)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should not leak connection references" do
|
81
|
+
c1 = @db.synchronize do |c|
|
82
|
+
@db.pool.instance_variable_get(:@connection_timestamps).should == {}
|
83
|
+
c
|
84
|
+
end
|
85
|
+
@db.pool.instance_variable_get(:@connection_timestamps).should have_key(c1)
|
86
|
+
|
87
|
+
c1.valid = false
|
88
|
+
@db.pool.connection_validation_timeout = -1
|
89
|
+
c2 = @db.synchronize do |c|
|
90
|
+
@db.pool.instance_variable_get(:@connection_timestamps).should == {}
|
91
|
+
c
|
92
|
+
end
|
93
|
+
c2.should_not equal(c1)
|
94
|
+
@db.pool.instance_variable_get(:@connection_timestamps).should_not have_key(c1)
|
95
|
+
@db.pool.instance_variable_get(:@connection_timestamps).should have_key(c2)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should handle case where determining validity requires a connection" do
|
99
|
+
@db.meta_def(:valid_connection?){|c| synchronize{}; true}
|
100
|
+
@db.pool.connection_validation_timeout = -1
|
101
|
+
c1 = @db.synchronize{|c| c}
|
102
|
+
@db.synchronize{|c| c}.should equal(c1)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "Sequel::ConnectionValidator with threaded pool" do
|
107
|
+
before do
|
108
|
+
@db = Sequel.mock
|
109
|
+
end
|
110
|
+
it_should_behave_like "Sequel::ConnectionValidator"
|
111
|
+
end
|
112
|
+
describe "Sequel::ConnectionValidator with sharded threaded pool" do
|
113
|
+
before do
|
114
|
+
@db = Sequel.mock(:servers=>{})
|
115
|
+
end
|
116
|
+
it_should_behave_like "Sequel::ConnectionValidator"
|
117
|
+
end
|
118
|
+
|
@@ -231,6 +231,10 @@ describe "pg_array extension" do
|
|
231
231
|
proc{@db.typecast_value(:integer_array, {})}.should raise_error(Sequel::InvalidValue)
|
232
232
|
end
|
233
233
|
|
234
|
+
it "should support SQL::AliasMethods" do
|
235
|
+
@db.select(Sequel.pg_array([1], :integer).as(:col1)).sql.should == 'SELECT ARRAY[1]::integer[] AS col1'
|
236
|
+
end
|
237
|
+
|
234
238
|
it "should support registering custom array types" do
|
235
239
|
Sequel::Postgres::PGArray.register('foo')
|
236
240
|
@db.typecast_value(:foo_array, []).should be_a_kind_of(Sequel::Postgres::PGArray)
|
@@ -181,5 +181,47 @@ describe Sequel::Model, "#sti_key" do
|
|
181
181
|
proc{StiTest2.dataset.row_proc.call(:kind=>1)}.should raise_error(Sequel::Error)
|
182
182
|
proc{StiTest2.dataset.row_proc.call(:kind=>2)}.should raise_error(Sequel::Error)
|
183
183
|
end
|
184
|
+
|
185
|
+
it "should work with non-bijective mappings" do
|
186
|
+
StiTest2.plugin :single_table_inheritance, :kind, :model_map=>{0=>'StiTest3', 1=>'StiTest3', 2=>'StiTest4'}
|
187
|
+
class ::StiTest3 < ::StiTest2; end
|
188
|
+
class ::StiTest4 < ::StiTest2; end
|
189
|
+
StiTest2.dataset.row_proc.call(:kind=>0).should be_a_instance_of(StiTest3)
|
190
|
+
StiTest2.dataset.row_proc.call(:kind=>1).should be_a_instance_of(StiTest3)
|
191
|
+
StiTest2.dataset.row_proc.call(:kind=>2).should be_a_instance_of(StiTest4)
|
192
|
+
|
193
|
+
StiTest3.create.kind.should == 1
|
194
|
+
StiTest4.create.kind.should == 2
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should work with non-bijective mappings and key map procs" do
|
198
|
+
StiTest2.plugin :single_table_inheritance, :kind,
|
199
|
+
:key_map=>proc{|model| model.to_s == 'StiTest4' ? 2 : [0,1] }
|
200
|
+
class ::StiTest3 < ::StiTest2; end
|
201
|
+
class ::StiTest4 < ::StiTest2; end
|
202
|
+
|
203
|
+
StiTest2.dataset.sql.should == "SELECT * FROM sti_test2s"
|
204
|
+
StiTest3.dataset.sql.should == "SELECT * FROM sti_test2s WHERE (sti_test2s.kind IN (0, 1))"
|
205
|
+
StiTest4.dataset.sql.should == "SELECT * FROM sti_test2s WHERE (sti_test2s.kind IN (2))"
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should create correct sql with non-bijective mappings" do
|
209
|
+
StiTest2.plugin :single_table_inheritance, :kind, :model_map=>{0=>'StiTest3', 1=>'StiTest3', 2=>'StiTest4'}
|
210
|
+
class ::StiTest3 < ::StiTest2; end
|
211
|
+
class ::StiTest4 < ::StiTest2; end
|
212
|
+
|
213
|
+
StiTest2.dataset.sql.should == "SELECT * FROM sti_test2s"
|
214
|
+
StiTest3.dataset.sql.should == "SELECT * FROM sti_test2s WHERE (sti_test2s.kind IN (0, 1))"
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should honor a :key_chooser" do
|
218
|
+
StiTest2.plugin :single_table_inheritance, :kind, :key_chooser => proc{|inst| inst.model.to_s.downcase }
|
219
|
+
class ::StiTest3 < ::StiTest2; end
|
220
|
+
class ::StiTest4 < ::StiTest2; end
|
221
|
+
|
222
|
+
StiTest3.create.kind.should == 'stitest3'
|
223
|
+
StiTest4.create.kind.should == 'stitest4'
|
224
|
+
end
|
225
|
+
|
184
226
|
end
|
185
227
|
end
|
@@ -110,6 +110,46 @@ describe "Touch plugin" do
|
|
110
110
|
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
|
111
111
|
end
|
112
112
|
|
113
|
+
specify "should be able to touch many_to_one associations" do
|
114
|
+
@Album.plugin :touch, :associations=>:artist
|
115
|
+
@Album.load(:id=>3, :artist_id=>4).touch
|
116
|
+
MODEL_DB.sqls.should == ["UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 3)",
|
117
|
+
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 4)"]
|
118
|
+
end
|
119
|
+
|
120
|
+
specify "should be able to touch many_to_one associations" do
|
121
|
+
@Artist.one_to_one :album, :class=>@Album, :key=>:artist_id
|
122
|
+
@Artist.plugin :touch, :associations=>:album
|
123
|
+
@a.touch
|
124
|
+
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
|
125
|
+
"UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
|
126
|
+
end
|
127
|
+
|
128
|
+
specify "should be able to touch many_to_many associations" do
|
129
|
+
@Artist.many_to_many :albums, :class=>@Album, :left_key=>:artist_id, :join_table=>:aa
|
130
|
+
@Artist.plugin :touch, :associations=>:albums
|
131
|
+
@a.touch
|
132
|
+
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
|
133
|
+
"SELECT albums.* FROM albums INNER JOIN aa ON ((aa.album_id = albums.id) AND (aa.artist_id = 1))",
|
134
|
+
"UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
|
135
|
+
end
|
136
|
+
|
137
|
+
specify "should be able to touch many_through_many associations" do
|
138
|
+
@Artist.plugin :many_through_many
|
139
|
+
@Artist.many_through_many :albums, [[:aa, :artist_id, :album_id]], :class=>@Album
|
140
|
+
@Artist.plugin :touch, :associations=>:albums
|
141
|
+
@a.touch
|
142
|
+
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
|
143
|
+
"SELECT albums.* FROM albums INNER JOIN aa ON ((aa.album_id = albums.id) AND (aa.artist_id = 1))",
|
144
|
+
"UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
|
145
|
+
end
|
146
|
+
|
147
|
+
specify "should handle touching many_to_one associations with no associated object" do
|
148
|
+
@Album.plugin :touch, :associations=>:artist
|
149
|
+
@Album.load(:id=>3, :artist_id=>nil).touch
|
150
|
+
MODEL_DB.sqls.should == ["UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 3)"]
|
151
|
+
end
|
152
|
+
|
113
153
|
specify "should not update a column that doesn't exist" do
|
114
154
|
@Album.plugin :touch, :column=>:x
|
115
155
|
a = @Album.load(:id=>1)
|
@@ -578,7 +578,7 @@ describe Sequel::Model do
|
|
578
578
|
specify "should validate uniqueness_of with allow_missing => true" do
|
579
579
|
@c.validates_uniqueness_of :value, :allow_missing => true
|
580
580
|
@m.should be_valid
|
581
|
-
@m.value =
|
581
|
+
@m.value = 1
|
582
582
|
@m.should_not be_valid
|
583
583
|
end
|
584
584
|
end
|
@@ -858,6 +858,12 @@ describe Sequel::Model, "Validations" do
|
|
858
858
|
@user = User.new(:username => "0records", :password => "anothertest")
|
859
859
|
@user.should be_valid
|
860
860
|
@user.errors.full_messages.should == []
|
861
|
+
|
862
|
+
User.db.sqls
|
863
|
+
@user = User.new(:password => "anothertest")
|
864
|
+
@user.should be_valid
|
865
|
+
@user.errors.full_messages.should == []
|
866
|
+
User.db.sqls.should == []
|
861
867
|
end
|
862
868
|
|
863
869
|
it "should validate the uniqueness of multiple columns" do
|
@@ -907,6 +913,18 @@ describe Sequel::Model, "Validations" do
|
|
907
913
|
@user = User.new(:username => "0records", :password => "anothertest")
|
908
914
|
@user.should be_valid
|
909
915
|
@user.errors.full_messages.should == []
|
916
|
+
|
917
|
+
User.db.sqls
|
918
|
+
@user = User.new(:password => "anothertest")
|
919
|
+
@user.should be_valid
|
920
|
+
@user.errors.full_messages.should == []
|
921
|
+
@user = User.new(:username => "0records")
|
922
|
+
@user.should be_valid
|
923
|
+
@user.errors.full_messages.should == []
|
924
|
+
@user = User.new
|
925
|
+
@user.should be_valid
|
926
|
+
@user.errors.full_messages.should == []
|
927
|
+
User.db.sqls.should == []
|
910
928
|
end
|
911
929
|
|
912
930
|
it "should have a validates block that contains multiple validations" do
|
@@ -331,6 +331,11 @@ describe "Sequel::Plugins::ValidationHelpers" do
|
|
331
331
|
@user = @c.load(:id=>3, :username => "0records", :password => "anothertest")
|
332
332
|
@user.should be_valid
|
333
333
|
|
334
|
+
MODEL_DB.sqls
|
335
|
+
@user = @c.new(:password => "anothertest")
|
336
|
+
@user.should be_valid
|
337
|
+
MODEL_DB.sqls.should == []
|
338
|
+
|
334
339
|
@user = @c.new(:username => "1record", :password => "anothertest")
|
335
340
|
@user.should_not be_valid
|
336
341
|
@user.errors.full_messages.should == ['username is already taken']
|
@@ -369,6 +374,18 @@ describe "Sequel::Plugins::ValidationHelpers" do
|
|
369
374
|
@user = @c.load(:id=>3, :username => "0records", :password => "anothertest")
|
370
375
|
@user.should be_valid
|
371
376
|
|
377
|
+
MODEL_DB.sqls
|
378
|
+
@user = @c.new(:password => "anothertest")
|
379
|
+
@user.should be_valid
|
380
|
+
@user.errors.full_messages.should == []
|
381
|
+
@user = @c.new(:username => "0records")
|
382
|
+
@user.should be_valid
|
383
|
+
@user.errors.full_messages.should == []
|
384
|
+
@user = @c.new
|
385
|
+
@user.should be_valid
|
386
|
+
@user.errors.full_messages.should == []
|
387
|
+
MODEL_DB.sqls.should == []
|
388
|
+
|
372
389
|
@user = @c.new(:username => "1record", :password => "anothertest")
|
373
390
|
@user.should_not be_valid
|
374
391
|
@user.errors.full_messages.should == ['username and password is already taken']
|
@@ -35,4 +35,18 @@ describe Sequel::Database do
|
|
35
35
|
specify "should not have the connection pool swallow non-StandardError based exceptions" do
|
36
36
|
proc{INTEGRATION_DB.pool.hold{raise Interrupt, "test"}}.should raise_error(Interrupt)
|
37
37
|
end
|
38
|
+
|
39
|
+
specify "should be able to disconnect connections more than once without exceptions" do
|
40
|
+
conn = INTEGRATION_DB.synchronize{|c| c}
|
41
|
+
INTEGRATION_DB.disconnect
|
42
|
+
INTEGRATION_DB.disconnect_connection(conn)
|
43
|
+
INTEGRATION_DB.disconnect_connection(conn)
|
44
|
+
end
|
45
|
+
|
46
|
+
cspecify "should provide ability to check connections for validity", [:do, :postgres] do
|
47
|
+
conn = INTEGRATION_DB.synchronize{|c| c}
|
48
|
+
INTEGRATION_DB.valid_connection?(conn).should be_true
|
49
|
+
INTEGRATION_DB.disconnect
|
50
|
+
INTEGRATION_DB.valid_connection?(conn).should be_false
|
51
|
+
end
|
38
52
|
end
|
@@ -717,19 +717,19 @@ describe Sequel::SQL::Constants do
|
|
717
717
|
cspecify "should have working CURRENT_TIME", [:do, :mysql], [:jdbc, :sqlite], [:mysql2] do
|
718
718
|
@db.create_table!(:constants){Time :t, :only_time=>true}
|
719
719
|
@ds.insert(:t=>Sequel::CURRENT_TIME)
|
720
|
-
(Time.now - @c[@ds.get(:t)]).should be_within(
|
720
|
+
(Time.now - @c[@ds.get(:t)]).should be_within(60).of(0)
|
721
721
|
end
|
722
722
|
|
723
723
|
cspecify "should have working CURRENT_TIMESTAMP", [:jdbc, :sqlite], [:swift] do
|
724
724
|
@db.create_table!(:constants){DateTime :ts}
|
725
725
|
@ds.insert(:ts=>Sequel::CURRENT_TIMESTAMP)
|
726
|
-
(Time.now - @c[@ds.get(:ts)]).should be_within(
|
726
|
+
(Time.now - @c[@ds.get(:ts)]).should be_within(60).of(0)
|
727
727
|
end
|
728
728
|
|
729
729
|
cspecify "should have working CURRENT_TIMESTAMP when used as a column default", [:jdbc, :sqlite], [:swift] do
|
730
730
|
@db.create_table!(:constants){DateTime :ts, :default=>Sequel::CURRENT_TIMESTAMP}
|
731
731
|
@ds.insert
|
732
|
-
(Time.now - @c[@ds.get(:ts)]).should be_within(
|
732
|
+
(Time.now - @c[@ds.get(:ts)]).should be_within(60).of(0)
|
733
733
|
end
|
734
734
|
end
|
735
735
|
|