sequel 3.28.0 → 3.29.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 (148) hide show
  1. data/CHANGELOG +119 -3
  2. data/Rakefile +5 -3
  3. data/bin/sequel +1 -5
  4. data/doc/model_hooks.rdoc +9 -1
  5. data/doc/opening_databases.rdoc +49 -40
  6. data/doc/prepared_statements.rdoc +27 -6
  7. data/doc/release_notes/3.28.0.txt +2 -2
  8. data/doc/release_notes/3.29.0.txt +459 -0
  9. data/doc/sharding.rdoc +7 -1
  10. data/doc/testing.rdoc +18 -9
  11. data/doc/transactions.rdoc +41 -1
  12. data/lib/sequel/adapters/ado.rb +28 -17
  13. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  14. data/lib/sequel/adapters/amalgalite.rb +11 -7
  15. data/lib/sequel/adapters/db2.rb +122 -70
  16. data/lib/sequel/adapters/dbi.rb +15 -15
  17. data/lib/sequel/adapters/do.rb +5 -36
  18. data/lib/sequel/adapters/do/mysql.rb +0 -5
  19. data/lib/sequel/adapters/do/postgres.rb +0 -5
  20. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  21. data/lib/sequel/adapters/firebird.rb +3 -6
  22. data/lib/sequel/adapters/ibmdb.rb +24 -16
  23. data/lib/sequel/adapters/informix.rb +2 -4
  24. data/lib/sequel/adapters/jdbc.rb +47 -11
  25. data/lib/sequel/adapters/jdbc/as400.rb +5 -24
  26. data/lib/sequel/adapters/jdbc/db2.rb +0 -5
  27. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  28. data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
  29. data/lib/sequel/adapters/jdbc/h2.rb +10 -12
  30. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  31. data/lib/sequel/adapters/jdbc/informix.rb +0 -5
  32. data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
  33. data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
  34. data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
  35. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
  36. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  37. data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
  38. data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
  39. data/lib/sequel/adapters/mock.rb +315 -0
  40. data/lib/sequel/adapters/mysql.rb +64 -51
  41. data/lib/sequel/adapters/mysql2.rb +15 -9
  42. data/lib/sequel/adapters/odbc.rb +13 -6
  43. data/lib/sequel/adapters/odbc/db2.rb +0 -4
  44. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  45. data/lib/sequel/adapters/openbase.rb +2 -4
  46. data/lib/sequel/adapters/oracle.rb +333 -51
  47. data/lib/sequel/adapters/postgres.rb +80 -27
  48. data/lib/sequel/adapters/shared/access.rb +0 -6
  49. data/lib/sequel/adapters/shared/db2.rb +13 -15
  50. data/lib/sequel/adapters/shared/firebird.rb +6 -6
  51. data/lib/sequel/adapters/shared/mssql.rb +23 -18
  52. data/lib/sequel/adapters/shared/mysql.rb +6 -6
  53. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
  54. data/lib/sequel/adapters/shared/oracle.rb +185 -30
  55. data/lib/sequel/adapters/shared/postgres.rb +35 -18
  56. data/lib/sequel/adapters/shared/progress.rb +0 -6
  57. data/lib/sequel/adapters/shared/sqlite.rb +116 -37
  58. data/lib/sequel/adapters/sqlite.rb +16 -8
  59. data/lib/sequel/adapters/swift.rb +5 -5
  60. data/lib/sequel/adapters/swift/mysql.rb +0 -5
  61. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  62. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  63. data/lib/sequel/adapters/tinytds.rb +13 -10
  64. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
  65. data/lib/sequel/core.rb +40 -0
  66. data/lib/sequel/database/connecting.rb +1 -2
  67. data/lib/sequel/database/dataset.rb +3 -3
  68. data/lib/sequel/database/dataset_defaults.rb +58 -0
  69. data/lib/sequel/database/misc.rb +62 -2
  70. data/lib/sequel/database/query.rb +113 -49
  71. data/lib/sequel/database/schema_methods.rb +7 -2
  72. data/lib/sequel/dataset/actions.rb +37 -19
  73. data/lib/sequel/dataset/features.rb +24 -0
  74. data/lib/sequel/dataset/graph.rb +7 -6
  75. data/lib/sequel/dataset/misc.rb +11 -3
  76. data/lib/sequel/dataset/mutation.rb +2 -3
  77. data/lib/sequel/dataset/prepared_statements.rb +6 -4
  78. data/lib/sequel/dataset/query.rb +46 -15
  79. data/lib/sequel/dataset/sql.rb +28 -4
  80. data/lib/sequel/extensions/named_timezones.rb +5 -0
  81. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  82. data/lib/sequel/model.rb +2 -1
  83. data/lib/sequel/model/associations.rb +115 -33
  84. data/lib/sequel/model/base.rb +91 -31
  85. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  86. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  87. data/lib/sequel/plugins/force_encoding.rb +6 -6
  88. data/lib/sequel/plugins/identity_map.rb +1 -1
  89. data/lib/sequel/plugins/many_through_many.rb +6 -10
  90. data/lib/sequel/plugins/prepared_statements.rb +12 -1
  91. data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
  92. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  93. data/lib/sequel/plugins/serialization.rb +6 -1
  94. data/lib/sequel/plugins/sharding.rb +0 -5
  95. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  96. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  97. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  98. data/lib/sequel/timezones.rb +42 -42
  99. data/lib/sequel/version.rb +1 -1
  100. data/spec/adapters/mssql_spec.rb +29 -29
  101. data/spec/adapters/mysql_spec.rb +86 -104
  102. data/spec/adapters/oracle_spec.rb +48 -76
  103. data/spec/adapters/postgres_spec.rb +98 -33
  104. data/spec/adapters/spec_helper.rb +0 -5
  105. data/spec/adapters/sqlite_spec.rb +24 -21
  106. data/spec/core/connection_pool_spec.rb +9 -15
  107. data/spec/core/core_sql_spec.rb +20 -31
  108. data/spec/core/database_spec.rb +491 -227
  109. data/spec/core/dataset_spec.rb +638 -1051
  110. data/spec/core/expression_filters_spec.rb +0 -1
  111. data/spec/core/mock_adapter_spec.rb +378 -0
  112. data/spec/core/object_graph_spec.rb +48 -114
  113. data/spec/core/schema_generator_spec.rb +3 -3
  114. data/spec/core/schema_spec.rb +51 -114
  115. data/spec/core/spec_helper.rb +3 -90
  116. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  117. data/spec/extensions/dataset_associations_spec.rb +199 -0
  118. data/spec/extensions/instance_hooks_spec.rb +71 -0
  119. data/spec/extensions/named_timezones_spec.rb +22 -2
  120. data/spec/extensions/nested_attributes_spec.rb +3 -0
  121. data/spec/extensions/schema_spec.rb +1 -1
  122. data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
  123. data/spec/extensions/serialization_spec.rb +5 -8
  124. data/spec/extensions/spec_helper.rb +4 -0
  125. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  126. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  127. data/spec/integration/associations_test.rb +123 -12
  128. data/spec/integration/dataset_test.rb +140 -47
  129. data/spec/integration/eager_loader_test.rb +19 -21
  130. data/spec/integration/model_test.rb +80 -1
  131. data/spec/integration/plugin_test.rb +179 -128
  132. data/spec/integration/prepared_statement_test.rb +92 -91
  133. data/spec/integration/schema_test.rb +42 -23
  134. data/spec/integration/spec_helper.rb +25 -31
  135. data/spec/integration/timezone_test.rb +38 -12
  136. data/spec/integration/transaction_test.rb +161 -34
  137. data/spec/integration/type_test.rb +3 -3
  138. data/spec/model/association_reflection_spec.rb +83 -7
  139. data/spec/model/associations_spec.rb +393 -676
  140. data/spec/model/base_spec.rb +186 -116
  141. data/spec/model/dataset_methods_spec.rb +7 -27
  142. data/spec/model/eager_loading_spec.rb +343 -867
  143. data/spec/model/hooks_spec.rb +160 -79
  144. data/spec/model/model_spec.rb +118 -165
  145. data/spec/model/plugins_spec.rb +7 -13
  146. data/spec/model/record_spec.rb +138 -207
  147. data/spec/model/spec_helper.rb +10 -73
  148. metadata +14 -8
@@ -16,11 +16,6 @@ end
16
16
 
17
17
  Sequel::Model.use_transactions = false
18
18
 
19
- $sqls = []
20
- def clear_sqls
21
- $sqls.clear
22
- end
23
-
24
19
  unless defined?(RSpec)
25
20
  module Spec::Matchers
26
21
  class BeWithin
@@ -34,46 +29,45 @@ unless defined?(RSpec)
34
29
  end
35
30
  end
36
31
 
37
- (defined?(RSpec) ? RSpec::Core::ExampleGroup : Spec::Example::ExampleGroup).class_eval do
38
- def log
39
- begin
40
- INTEGRATION_DB.loggers << Logger.new(STDOUT)
41
- yield
42
- ensure
43
- INTEGRATION_DB.loggers.pop
44
- end
45
- end
46
-
47
- def self.log_specify(message, &block)
48
- specify(message){log{instance_eval(&block)}}
49
- end
50
-
51
- def self.cspecify(message, *checked, &block)
52
- return specify(message, &block) if ENV['SEQUEL_NO_PENDING']
53
- pending = false
32
+ def Sequel.guarded?(*checked)
33
+ unless ENV['SEQUEL_NO_PENDING']
54
34
  checked.each do |c|
55
35
  case c
56
36
  when INTEGRATION_DB.database_type
57
- pending = c
37
+ return c
58
38
  when Array
59
39
  case c.length
60
40
  when 1
61
- pending = c if c.first == INTEGRATION_DB.adapter_scheme
41
+ return c if c.first == INTEGRATION_DB.adapter_scheme
62
42
  when 2
63
43
  if c.first.is_a?(Proc)
64
- pending = c if c.first.call(INTEGRATION_DB) && c.last == INTEGRATION_DB.database_type
44
+ return c if c.first.call(INTEGRATION_DB) && c.last == INTEGRATION_DB.database_type
65
45
  elsif c.last.is_a?(Proc)
66
- pending = c if c.first == INTEGRATION_DB.adapter_scheme && c.last.call(INTEGRATION_DB)
46
+ return c if c.first == INTEGRATION_DB.adapter_scheme && c.last.call(INTEGRATION_DB)
67
47
  else
68
- pending = c if c.first == INTEGRATION_DB.adapter_scheme && c.last == INTEGRATION_DB.database_type
48
+ return c if c.first == INTEGRATION_DB.adapter_scheme && c.last == INTEGRATION_DB.database_type
69
49
  end
70
50
  when 3
71
- pending = c if c[0] == INTEGRATION_DB.adapter_scheme && c[1] == INTEGRATION_DB.database_type && c[2].call(INTEGRATION_DB)
51
+ return c if c[0] == INTEGRATION_DB.adapter_scheme && c[1] == INTEGRATION_DB.database_type && c[2].call(INTEGRATION_DB)
72
52
  end
73
53
  end
74
- break if pending
75
54
  end
76
- if pending
55
+ end
56
+ false
57
+ end
58
+
59
+ (defined?(RSpec) ? RSpec::Core::ExampleGroup : Spec::Example::ExampleGroup).class_eval do
60
+ def log
61
+ begin
62
+ INTEGRATION_DB.loggers << Logger.new(STDOUT)
63
+ yield
64
+ ensure
65
+ INTEGRATION_DB.loggers.pop
66
+ end
67
+ end
68
+
69
+ def self.cspecify(message, *checked, &block)
70
+ if pending = Sequel.guarded?(*checked)
77
71
  specify(message){pending("Not yet working on #{Array(pending).join(', ')}", &block)}
78
72
  else
79
73
  specify(message, &block)
@@ -88,7 +82,7 @@ if defined?(INTEGRATION_DB) || defined?(INTEGRATION_URL) || ENV['SEQUEL_INTEGRAT
88
82
  #INTEGRATION_DB.instance_variable_set(:@server_version, 80100)
89
83
  end
90
84
  else
91
- INTEGRATION_DB = Sequel.sqlite('', :quote_identifiers=>false)
85
+ INTEGRATION_DB = Sequel.sqlite
92
86
  end
93
87
 
94
88
  if INTEGRATION_DB.adapter_scheme == :ibmdb
@@ -1,15 +1,17 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
3
  describe "Sequel timezone support" do
4
- def test_timezone
4
+ def test_timezone(timezone=Sequel.application_timezone)
5
+ tz = timezone
6
+ Sequel.datetime_class = Time
5
7
  # Tests should cover both DST and non-DST times.
6
8
  [Time.now, Time.local(2010,1,1,12), Time.local(2010,6,1,12)].each do |t|
7
9
  @db[:t].insert(t)
8
10
  t2 = @db[:t].single_value
9
- t2 = Sequel.database_to_application_timestamp(t2.to_s) unless t2.is_a?(Time)
11
+ t2 = @db.to_application_timestamp(t2.to_s) unless t2.is_a?(Time)
10
12
  (t2 - t).should be_within(2).of(0)
11
- t2.utc_offset.should == 0 if Sequel.application_timezone == :utc
12
- t2.utc_offset.should == t.getlocal.utc_offset if Sequel.application_timezone == :local
13
+ t2.utc_offset.should == 0 if timezone == :utc
14
+ t2.utc_offset.should == t.getlocal.utc_offset if timezone == :local
13
15
  @db[:t].delete
14
16
  end
15
17
 
@@ -19,10 +21,10 @@ describe "Sequel timezone support" do
19
21
  [DateTime.now, DateTime.civil(2010,1,1,12,0,0,local_std_offset), DateTime.civil(2010,6,1,12,0,0,local_dst_offset)].each do |dt|
20
22
  @db[:t].insert(dt)
21
23
  dt2 = @db[:t].single_value
22
- dt2 = Sequel.database_to_application_timestamp(dt2.to_s) unless dt2.is_a?(DateTime)
24
+ dt2 = @db.to_application_timestamp(dt2.to_s) unless dt2.is_a?(DateTime)
23
25
  (dt2 - dt).should be_within(0.00002).of(0)
24
- dt2.offset.should == 0 if Sequel.application_timezone == :utc
25
- dt2.offset.should == dt.offset if Sequel.application_timezone == :local
26
+ dt2.offset.should == 0 if timezone == :utc
27
+ dt2.offset.should == dt.offset if timezone == :local
26
28
  @db[:t].delete
27
29
  end
28
30
  end
@@ -32,30 +34,54 @@ describe "Sequel timezone support" do
32
34
  @db.create_table!(:t){DateTime :t}
33
35
  end
34
36
  after do
35
- @db.drop_table(:t)
37
+ @db.timezone = nil
36
38
  Sequel.default_timezone = nil
37
39
  Sequel.datetime_class = Time
40
+ @db.drop_table(:t)
38
41
  end
39
42
 
40
- cspecify "should support using UTC for database storage and local time for the application", [:swift], [:tinytds], [:do, proc{|db| db.database_type != :sqlite}] do
43
+ cspecify "should support using UTC for database storage and local time for the application", [:swift], [:tinytds], [:do, :mysql], [:do, :postgres], [:oracle] do
41
44
  Sequel.database_timezone = :utc
42
45
  Sequel.application_timezone = :local
43
46
  test_timezone
47
+ Sequel.database_timezone = nil
48
+ @db.timezone = :utc
49
+ test_timezone
44
50
  end
45
51
 
46
- cspecify "should support using local time for database storage and UTC for the application", [:swift], [:tinytds], [:do, proc{|db| db.database_type != :sqlite}] do
52
+ cspecify "should support using local time for database storage and UTC for the application", [:swift], [:tinytds], [:do, :mysql], [:do, :postgres], [:oracle] do
47
53
  Sequel.database_timezone = :local
48
54
  Sequel.application_timezone = :utc
49
55
  test_timezone
56
+ Sequel.database_timezone = nil
57
+ @db.timezone = :local
58
+ test_timezone
50
59
  end
51
60
 
52
- cspecify "should support using UTC for both database storage and for application", [:swift], [:do, proc{|db| db.database_type != :sqlite}] do
61
+ cspecify "should support using UTC for both database storage and for application", [:swift], [:do, :mysql], [:do, :postgres], [:oracle] do
53
62
  Sequel.default_timezone = :utc
54
63
  test_timezone
64
+ Sequel.database_timezone = :local
65
+ @db.timezone = :utc
66
+ test_timezone
55
67
  end
56
68
 
57
- cspecify "should support using local time for both database storage and for application", [:do, proc{|db| db.database_type != :sqlite}] do
69
+ cspecify "should support using local time for both database storage and for application", [:do, :mysql], [:do, :postgres], [:oracle] do
58
70
  Sequel.default_timezone = :local
59
71
  test_timezone
72
+ Sequel.database_timezone = :utc
73
+ @db.timezone = :local
74
+ test_timezone
75
+ end
76
+
77
+ specify "should allow overriding the database_timezone on a per-database basis" do
78
+ Sequel.database_timezone = :utc
79
+ @db.timezone = :local
80
+ t = Time.now
81
+ @db[:t].insert(t)
82
+ s = @db[:t].get(:t.cast(String))
83
+ if o = Date._parse(s)[:offset]
84
+ o.should == t.utc_offset
85
+ end
60
86
  end
61
87
  end
@@ -1,14 +1,16 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
3
  describe "Database transactions" do
4
- before do
4
+ before(:all) do
5
5
  @db = INTEGRATION_DB
6
6
  @db.drop_table(:items) if @db.table_exists?(:items)
7
7
  @db.create_table(:items, :engine=>'InnoDB'){String :name; Integer :value}
8
8
  @d = @db[:items]
9
- clear_sqls
10
9
  end
11
- after do
10
+ before do
11
+ @d.delete
12
+ end
13
+ after(:all) do
12
14
  @db.drop_table(:items) if @db.table_exists?(:items)
13
15
  end
14
16
 
@@ -21,6 +23,13 @@ describe "Database transactions" do
21
23
  @db.transaction{|conn| conn.should_not == nil}
22
24
  end
23
25
 
26
+ specify "should have #in_transaction? work correctly" do
27
+ @db.in_transaction?.should be_false
28
+ c = nil
29
+ @db.transaction{c = @db.in_transaction?}
30
+ c.should be_true
31
+ end
32
+
24
33
  specify "should correctly rollback transactions" do
25
34
  proc do
26
35
  @db.transaction do
@@ -29,12 +38,22 @@ describe "Database transactions" do
29
38
  end
30
39
  end.should raise_error(Interrupt)
31
40
 
41
+ @db.transaction do
42
+ @d << {:name => 'abc', :value => 1}
43
+ raise Sequel::Rollback
44
+ end.should be_nil
45
+
32
46
  proc do
33
- @db.transaction do
47
+ @db.transaction(:rollback=>:reraise) do
34
48
  @d << {:name => 'abc', :value => 1}
35
49
  raise Sequel::Rollback
36
50
  end
37
- end.should_not raise_error
51
+ end.should raise_error(Sequel::Rollback)
52
+
53
+ @db.transaction(:rollback=>:always) do
54
+ @d << {:name => 'abc', :value => 1}
55
+ 2
56
+ end.should be_nil
38
57
 
39
58
  @d.count.should == 0
40
59
  end
@@ -126,6 +145,14 @@ describe "Database transactions" do
126
145
  @db.rollback_prepared_transaction('XYZ')
127
146
  @d.select_order_map(:name).should == []
128
147
  end
148
+
149
+ if INTEGRATION_DB.supports_savepoints?
150
+ specify "should support savepoints when using prepared transactions" do
151
+ @db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@d << {:name => '1'}}}
152
+ @db.commit_prepared_transaction('XYZ')
153
+ @d.select_order_map(:name).should == ['1']
154
+ end
155
+ end
129
156
  end
130
157
 
131
158
  specify "should support all transaction isolation levels" do
@@ -135,43 +162,143 @@ describe "Database transactions" do
135
162
  end
136
163
  end
137
164
 
138
- if (! defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or (RUBY_ENGINE == 'rbx' && ![[:do, :sqlite], [:tinytds, :mssql]].include?([INTEGRATION_DB.adapter_scheme, INTEGRATION_DB.database_type]))) and RUBY_VERSION < '1.9'
139
- specify "should handle Thread#kill for transactions inside threads" do
140
- q = Queue.new
141
- q1 = Queue.new
142
- t = Thread.new do
143
- @db.transaction do
144
- @d << {:name => 'abc', :value => 1}
145
- q1.push nil
146
- q.pop
147
- @d << {:name => 'def', :value => 2}
165
+ specify "should support after_commit outside transactions" do
166
+ c = nil
167
+ @db.after_commit{c = 1}
168
+ c.should == 1
169
+ end
170
+
171
+ specify "should support after_rollback outside transactions" do
172
+ c = nil
173
+ @db.after_rollback{c = 1}
174
+ c.should be_nil
175
+ end
176
+
177
+ specify "should support after_commit inside transactions" do
178
+ c = nil
179
+ @db.transaction{@db.after_commit{c = 1}; c.should be_nil}
180
+ c.should == 1
181
+ end
182
+
183
+ specify "should support after_rollback inside transactions" do
184
+ c = nil
185
+ @db.transaction{@db.after_rollback{c = 1}; c.should be_nil}
186
+ c.should be_nil
187
+ end
188
+
189
+ specify "should not call after_commit if the transaction rolls back" do
190
+ c = nil
191
+ @db.transaction{@db.after_commit{c = 1}; c.should be_nil; raise Sequel::Rollback}
192
+ c.should be_nil
193
+ end
194
+
195
+ specify "should call after_rollback if the transaction rolls back" do
196
+ c = nil
197
+ @db.transaction{@db.after_rollback{c = 1}; c.should be_nil; raise Sequel::Rollback}
198
+ c.should == 1
199
+ end
200
+
201
+ specify "should support multiple after_commit blocks inside transactions" do
202
+ c = []
203
+ @db.transaction{@db.after_commit{c << 1}; @db.after_commit{c << 2}; c.should == []}
204
+ c.should == [1, 2]
205
+ end
206
+
207
+ specify "should support multiple after_rollback blocks inside transactions" do
208
+ c = []
209
+ @db.transaction{@db.after_rollback{c << 1}; @db.after_rollback{c << 2}; c.should == []; raise Sequel::Rollback}
210
+ c.should == [1, 2]
211
+ end
212
+
213
+ specify "should support after_commit inside nested transactions" do
214
+ c = nil
215
+ @db.transaction{@db.transaction{@db.after_commit{c = 1}}; c.should be_nil}
216
+ c.should == 1
217
+ end
218
+
219
+ specify "should support after_rollback inside nested transactions" do
220
+ c = nil
221
+ @db.transaction{@db.transaction{@db.after_rollback{c = 1}}; c.should be_nil; raise Sequel::Rollback}
222
+ c.should == 1
223
+ end
224
+
225
+ if INTEGRATION_DB.supports_savepoints?
226
+ specify "should support after_commit inside savepoints" do
227
+ c = nil
228
+ @db.transaction{@db.transaction(:savepoint=>true){@db.after_commit{c = 1}}; c.should be_nil}
229
+ c.should == 1
230
+ end
231
+
232
+ specify "should support after_rollback inside savepoints" do
233
+ c = nil
234
+ @db.transaction{@db.transaction(:savepoint=>true){@db.after_rollback{c = 1}}; c.should be_nil; raise Sequel::Rollback}
235
+ c.should == 1
236
+ end
237
+ end
238
+
239
+ if INTEGRATION_DB.supports_prepared_transactions?
240
+ specify "should raise an error if you attempt to use after_commit or after_rollback inside a prepared transaction" do
241
+ proc{@db.transaction(:prepare=>'XYZ'){@db.after_commit{}}}.should raise_error(Sequel::Error)
242
+ proc{@db.transaction(:prepare=>'XYZ'){@db.after_rollback{}}}.should raise_error(Sequel::Error)
243
+ end
244
+
245
+ if INTEGRATION_DB.supports_savepoints?
246
+ specify "should raise an error if you attempt to use after_commit or after rollback inside a savepoint in a prepared transaction" do
247
+ proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_commit{}}}}.should raise_error(Sequel::Error)
248
+ proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_rollback{}}}}.should raise_error(Sequel::Error)
148
249
  end
149
250
  end
150
- q1.pop
151
- t.kill
152
- @d.count.should == 0
153
251
  end
252
+ end
154
253
 
155
- if INTEGRATION_DB.supports_savepoints?
156
- specify "should handle Thread#kill for transactions with savepoints inside threads" do
157
- q = Queue.new
158
- q1 = Queue.new
159
- t = Thread.new do
160
- @db.transaction do
161
- @d << {:name => 'abc', :value => 1}
162
- @db.transaction(:savepoint=>true) do
163
- @d << {:name => 'def', :value => 2}
254
+ if (! defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or (RUBY_ENGINE == 'rbx' && !Sequel.guarded?([:do, :sqlite], [:tinytds, :mssql]))) and RUBY_VERSION < '1.9'
255
+ describe "Database transactions and Thread#kill" do
256
+ before do
257
+ @db = INTEGRATION_DB
258
+ @db.drop_table(:items) if @db.table_exists?(:items)
259
+ @db.create_table(:items, :engine=>'InnoDB'){String :name; Integer :value}
260
+ @d = @db[:items]
261
+ end
262
+ after do
263
+ @db.drop_table(:items) if @db.table_exists?(:items)
264
+ end
265
+
266
+ specify "should handle transactions inside threads" do
267
+ q = Queue.new
268
+ q1 = Queue.new
269
+ t = Thread.new do
270
+ @db.transaction do
271
+ @d << {:name => 'abc', :value => 1}
164
272
  q1.push nil
165
273
  q.pop
166
- @d << {:name => 'ghi', :value => 3}
274
+ @d << {:name => 'def', :value => 2}
167
275
  end
168
- @d << {:name => 'jkl', :value => 4}
276
+ end
277
+ q1.pop
278
+ t.kill
279
+ @d.count.should == 0
280
+ end
281
+
282
+ if INTEGRATION_DB.supports_savepoints?
283
+ specify "should handle transactions with savepoints inside threads" do
284
+ q = Queue.new
285
+ q1 = Queue.new
286
+ t = Thread.new do
287
+ @db.transaction do
288
+ @d << {:name => 'abc', :value => 1}
289
+ @db.transaction(:savepoint=>true) do
290
+ @d << {:name => 'def', :value => 2}
291
+ q1.push nil
292
+ q.pop
293
+ @d << {:name => 'ghi', :value => 3}
294
+ end
295
+ @d << {:name => 'jkl', :value => 4}
296
+ end
297
+ end
298
+ q1.pop
299
+ t.kill
300
+ @d.count.should == 0
169
301
  end
170
302
  end
171
- q1.pop
172
- t.kill
173
- @d.count.should == 0
174
303
  end
175
304
  end
176
- end
177
- end
@@ -60,7 +60,7 @@ describe "Supported types" do
60
60
  ds.all.should == [{:name=>'Test User'}]
61
61
  end
62
62
 
63
- cspecify "should support generic date type", [:do, :sqlite], [:jdbc, :sqlite], :mssql do
63
+ cspecify "should support generic date type", [:do, :sqlite], [:jdbc, :sqlite], :mssql, :oracle do
64
64
  ds = create_items_table_with_column(:dat, Date)
65
65
  d = Date.today
66
66
  ds.insert(:dat => d)
@@ -68,7 +68,7 @@ describe "Supported types" do
68
68
  ds.first[:dat].to_s.should == d.to_s
69
69
  end
70
70
 
71
- cspecify "should support generic time type", [:do], [:swift], [:odbc], [:jdbc, :mssql], [:jdbc, :postgres], [:mysql2], [:tinytds] do
71
+ cspecify "should support generic time type", [:do], [:swift], [:odbc], [:jdbc, :mssql], [:jdbc, :postgres], [:jdbc, :sqlite], [:mysql2], [:tinytds], :oracle do
72
72
  ds = create_items_table_with_column(:tim, Time, :only_time=>true)
73
73
  t = Sequel::SQLTime.now
74
74
  ds.insert(:tim => t)
@@ -100,7 +100,7 @@ describe "Supported types" do
100
100
  ds.first[:name].should be_a_kind_of(::Sequel::SQL::Blob)
101
101
  end
102
102
 
103
- cspecify "should support generic boolean type", [:do, :sqlite], [:jdbc, :sqlite], [:jdbc, :db2], [:odbc, :mssql] do
103
+ cspecify "should support generic boolean type", [:do, :sqlite], [:jdbc, :sqlite], [:jdbc, :db2], [:odbc, :mssql], :oracle do
104
104
  ds = create_items_table_with_column(:number, TrueClass)
105
105
  ds.insert(:number => true)
106
106
  ds.all.should == [{:number=>true}]