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.
Files changed (89) hide show
  1. data/CHANGELOG +40 -0
  2. data/README.rdoc +2 -2
  3. data/doc/advanced_associations.rdoc +12 -0
  4. data/doc/bin_sequel.rdoc +144 -0
  5. data/doc/migration.rdoc +1 -1
  6. data/doc/object_model.rdoc +29 -0
  7. data/doc/release_notes/3.41.0.txt +155 -0
  8. data/lib/sequel/adapters/ado.rb +4 -4
  9. data/lib/sequel/adapters/amalgalite.rb +0 -5
  10. data/lib/sequel/adapters/cubrid.rb +2 -2
  11. data/lib/sequel/adapters/db2.rb +9 -5
  12. data/lib/sequel/adapters/dbi.rb +4 -6
  13. data/lib/sequel/adapters/do.rb +4 -5
  14. data/lib/sequel/adapters/firebird.rb +8 -4
  15. data/lib/sequel/adapters/ibmdb.rb +2 -3
  16. data/lib/sequel/adapters/informix.rb +0 -6
  17. data/lib/sequel/adapters/jdbc.rb +11 -7
  18. data/lib/sequel/adapters/jdbc/db2.rb +22 -0
  19. data/lib/sequel/adapters/jdbc/derby.rb +5 -5
  20. data/lib/sequel/adapters/jdbc/h2.rb +0 -5
  21. data/lib/sequel/adapters/jdbc/jtds.rb +1 -1
  22. data/lib/sequel/adapters/jdbc/sqlserver.rb +6 -0
  23. data/lib/sequel/adapters/mock.rb +3 -3
  24. data/lib/sequel/adapters/mysql.rb +7 -7
  25. data/lib/sequel/adapters/mysql2.rb +0 -5
  26. data/lib/sequel/adapters/odbc.rb +4 -4
  27. data/lib/sequel/adapters/openbase.rb +4 -6
  28. data/lib/sequel/adapters/oracle.rb +14 -6
  29. data/lib/sequel/adapters/postgres.rb +12 -8
  30. data/lib/sequel/adapters/shared/db2.rb +5 -0
  31. data/lib/sequel/adapters/shared/firebird.rb +10 -0
  32. data/lib/sequel/adapters/shared/mssql.rb +43 -1
  33. data/lib/sequel/adapters/shared/mysql.rb +1 -0
  34. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +1 -1
  35. data/lib/sequel/adapters/shared/postgres.rb +12 -0
  36. data/lib/sequel/adapters/shared/sqlite.rb +32 -0
  37. data/lib/sequel/adapters/sqlite.rb +9 -8
  38. data/lib/sequel/adapters/swift.rb +3 -8
  39. data/lib/sequel/adapters/tinytds.rb +5 -5
  40. data/lib/sequel/connection_pool.rb +13 -19
  41. data/lib/sequel/connection_pool/sharded_single.rb +12 -12
  42. data/lib/sequel/connection_pool/sharded_threaded.rb +37 -17
  43. data/lib/sequel/connection_pool/single.rb +6 -3
  44. data/lib/sequel/connection_pool/threaded.rb +33 -13
  45. data/lib/sequel/database/connecting.rb +28 -1
  46. data/lib/sequel/database/logging.rb +1 -1
  47. data/lib/sequel/database/misc.rb +2 -5
  48. data/lib/sequel/database/query.rb +2 -2
  49. data/lib/sequel/database/schema_generator.rb +1 -1
  50. data/lib/sequel/database/schema_methods.rb +3 -0
  51. data/lib/sequel/dataset/query.rb +8 -4
  52. data/lib/sequel/dataset/sql.rb +7 -0
  53. data/lib/sequel/extensions/arbitrary_servers.rb +1 -1
  54. data/lib/sequel/extensions/connection_validator.rb +109 -0
  55. data/lib/sequel/extensions/pg_array.rb +2 -0
  56. data/lib/sequel/extensions/pg_hstore.rb +2 -0
  57. data/lib/sequel/extensions/pg_json.rb +4 -0
  58. data/lib/sequel/extensions/pg_range.rb +1 -0
  59. data/lib/sequel/extensions/pg_row.rb +4 -0
  60. data/lib/sequel/plugins/prepared_statements.rb +2 -1
  61. data/lib/sequel/plugins/single_table_inheritance.rb +53 -10
  62. data/lib/sequel/plugins/touch.rb +18 -6
  63. data/lib/sequel/plugins/validation_class_methods.rb +1 -0
  64. data/lib/sequel/plugins/validation_helpers.rb +3 -1
  65. data/lib/sequel/sql.rb +61 -19
  66. data/lib/sequel/version.rb +1 -1
  67. data/spec/adapters/firebird_spec.rb +52 -38
  68. data/spec/adapters/mssql_spec.rb +67 -0
  69. data/spec/adapters/mysql_spec.rb +192 -116
  70. data/spec/adapters/postgres_spec.rb +133 -70
  71. data/spec/adapters/spec_helper.rb +7 -0
  72. data/spec/adapters/sqlite_spec.rb +34 -1
  73. data/spec/core/connection_pool_spec.rb +79 -75
  74. data/spec/core/database_spec.rb +9 -4
  75. data/spec/core/dataset_spec.rb +15 -0
  76. data/spec/core/expression_filters_spec.rb +40 -2
  77. data/spec/extensions/connection_validator_spec.rb +118 -0
  78. data/spec/extensions/pg_array_spec.rb +4 -0
  79. data/spec/extensions/single_table_inheritance_spec.rb +42 -0
  80. data/spec/extensions/touch_spec.rb +40 -0
  81. data/spec/extensions/validation_class_methods_spec.rb +19 -1
  82. data/spec/extensions/validation_helpers_spec.rb +17 -0
  83. data/spec/integration/database_test.rb +14 -0
  84. data/spec/integration/dataset_test.rb +3 -3
  85. data/spec/integration/plugin_test.rb +41 -12
  86. data/spec/integration/schema_test.rb +14 -0
  87. data/spec/integration/spec_helper.rb +7 -0
  88. data/spec/integration/type_test.rb +3 -0
  89. metadata +9 -3
@@ -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 {1234}
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){12345}
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{@test = rand(100)}
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) do
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
@@ -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::VirtualRow)}
555
- Sequel.expr{self.should be_a_kind_of(Sequel::SQL::VirtualRow)}
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 = nil
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(2).of(0)
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(2).of(0)
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(2).of(0)
732
+ (Time.now - @c[@ds.get(:ts)]).should be_within(60).of(0)
733
733
  end
734
734
  end
735
735