sequel 5.15.0 → 5.16.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 965fa50e6e91a5630a4e484651180b38b9d2eb2c785be8b91dd5b099e3ba5be6
4
- data.tar.gz: 3c3c5bd93d51326fff0081272e41a0a23b0dbb47d393603f073cbc0f0486e6c7
3
+ metadata.gz: 50240675066a0bd3e480a52ba3ff556b962ae3d8403fb22ee210272f2fffb023
4
+ data.tar.gz: d1c86ff37811732211b00b251c49bf7c4929ca7b18bf7c6ffeda1b8d0335482f
5
5
  SHA512:
6
- metadata.gz: a633436d4a066e195e847cffc7dd68d0cd2902915ddca33d5df724dc020aee22dbd95a261f8b15ea1581a73517d5736423a8693f40a3ef59fb27c88b8c24ca01
7
- data.tar.gz: bee56c79793138296ced8395deabf2652a68fe2de3bc4f144470d885b253883017e15ca0281e36e04c6064b590b505daed285b23699140e77cae119bddee3914
6
+ metadata.gz: 6a5a5b35a91ff83c6a0dab3e5cb88e26d79dced018f46fa78ad8be2b4da37c602adba56f849c0591c12f976006ea6e511bb3153478e70f3824ac940772f14de6
7
+ data.tar.gz: 50f5217691ec39036999623ce8d791fc93c270876d857e30b53892def7d36e0f3c99a3c69b13f97162f45b49dd066f1a5fcbf8b9660f96a1cd5c0c5a23c9ee72
data/CHANGELOG CHANGED
@@ -1,3 +1,31 @@
1
+ === 5.16.0 (2019-01-02)
2
+
3
+ * Convert integer columns to bigint columns when copying SQLite databases to other databases using bin/sequel -C (jeremyevans) (#1584)
4
+
5
+ * Use nicer error messages for missing or empty migration directories (Lavode) (#1585)
6
+
7
+ * Make alter table emulation work correctly in SQLite 3.26.0+ (jeremyevans) (#1582)
8
+
9
+ * Do not unset new one_to_one associated objects' reciprocal associations before saving associated objects in the nested_attributes plugin (jeremyevans)
10
+
11
+ * Do not validate new one_to_one associated objects twice when saving in the nested_attributes plugin (jeremyevans)
12
+
13
+ * Fix :qualify_tables option to class_table_inheritance plugin to work correctly with subclasses of subclasses (benalavi) (#1581)
14
+
15
+ * Make class_table_inheritance plugin use the schema cache instead of sending a query to get columns for tables (kenaniah) (#1580)
16
+
17
+ * Remove loading of mysqlplus in the mysql adapter (jeremyevans)
18
+
19
+ * Make mysql adapter work correctly on ruby 2.6+ (jeremyevans)
20
+
21
+ * Add Database#rollback_on_exit to rollback transactions instead of committing them when exiting the transaction block (jeremyevans)
22
+
23
+ * Enable window functions in SQLite 3.26.0+ (jeremyevans)
24
+
25
+ * Do not override existing methods when creating Sequel::Model attribute getter/setter methods (jeremyevans) (#1578)
26
+
27
+ * Use parentheses for expressions being subscripted (e.g. (array_agg(column))[1]) (jeremyevans)
28
+
1
29
  === 5.15.0 (2018-12-01)
2
30
 
3
31
  * Add :conn_str option in the postgres adapter for PostgreSQL connection strings, if the pg driver is used (graywolf) (#1572)
data/bin/sequel CHANGED
@@ -195,6 +195,10 @@ begin
195
195
  same_db = DB.database_type==TO_DB.database_type
196
196
  index_opts = {:same_db=>same_db}
197
197
  index_opts[:index_names] = :namespace if !DB.global_index_namespace? && TO_DB.global_index_namespace?
198
+ if DB.database_type == :sqlite && !same_db
199
+ # SQLite integer types allows 64-bit integers
200
+ TO_DB.extension :integer64
201
+ end
198
202
 
199
203
  puts "Databases connections successful"
200
204
  schema_migration = eval(DB.dump_schema_migration(:indexes=>false, :same_db=>same_db))
@@ -233,7 +233,7 @@ jdbc-h2 :: jdbc-h2 versions greater than 1.3.175 have issues with ORDER BY not w
233
233
 
234
234
  === mysql
235
235
 
236
- Requires: mysqlplus (or mysql if mysqlplus is not available)
236
+ Requires: mysql
237
237
 
238
238
  The MySQL adapter does not support the pure-ruby mysql.rb driver, it requires the C-extension driver.
239
239
 
@@ -0,0 +1,110 @@
1
+ = New Features
2
+
3
+ * Database#rollback_on_exit has been added, which allows you to
4
+ rollback transactions instead of committing them when exiting
5
+ the transaction block. Previously, the only way to rollback
6
+ a transaction from inside a transaction block was to raise
7
+ an exception. This allows you to tell Sequel to roll the
8
+ transaction back on exit, and then use return or throw to exit
9
+ the transaction block.
10
+
11
+ Database#rollback_on_exit supports savepoints, including
12
+ multiple savepoint levels, as well as canceling rollbacks:
13
+
14
+ DB.transaction do # BEGIN
15
+ DB.rollback_on_exit
16
+ end # ROLLBACK
17
+
18
+ DB.transaction do # BEGIN
19
+ DB.transaction(savepoint: true) do # SAVEPOINT
20
+ DB.rollback_on_exit(savepoint: true)
21
+ end # ROLLBACK TO SAVEPOINT
22
+ end # COMMIT
23
+
24
+ DB.transaction do # BEGIN
25
+ DB.transaction(savepoint: true) do # SAVEPOINT
26
+ DB.transaction(savepoint: true) do # SAVEPOINT
27
+ DB.rollback_on_exit(savepoint: true)
28
+ end # ROLLBACK TO SAVEPOINT
29
+ end # RELEASE SAVEPOINT
30
+ end # COMMIT
31
+
32
+ DB.transaction do # BEGIN
33
+ DB.transaction(savepoint: true) do # SAVEPOINT
34
+ DB.rollback_on_exit(savepoint: true)
35
+ end # ROLLBACK TO SAVEPOINT
36
+ end # COMMIT
37
+
38
+ DB.transaction do # BEGIN
39
+ DB.transaction(savepoint: true) do # SAVEPOINT
40
+ DB.transaction(savepoint: true) do # SAVEPOINT
41
+ DB.rollback_on_exit(savepoint: 2)
42
+ end # ROLLBACK TO SAVEPOINT
43
+ end # ROLLBACK TO SAVEPOINT
44
+ end # COMMIT
45
+
46
+ DB.transaction do # BEGIN
47
+ DB.transaction(savepoint: true) do # SAVEPOINT
48
+ DB.transaction(savepoint: true) do # SAVEPOINT
49
+ DB.rollback_on_exit(savepoint: 3)
50
+ end # ROLLBACK TO SAVEPOINT
51
+ end # ROLLBACK TO SAVEPOINT
52
+ end # ROLLBACK
53
+
54
+ DB.transaction do # BEGIN
55
+ DB.rollback_on_exit
56
+ DB.rollback_on_exit(cancel: true)
57
+ end # COMMIT
58
+
59
+ * Sequel now supports window functions on SQLite 3.26.0+. SQLite
60
+ technically supports window functions on 3.25.0+, but enabling
61
+ window function support in Sequel opens up a code path that
62
+ generates queries that cause older versions of SQLite to produce a
63
+ segmentation fault. This bug in SQLite has been fixed in 3.26.0.
64
+
65
+ = Other Improvements
66
+
67
+ * Sequel::Model no longer overrides existing methods when defining
68
+ getters and setters. Historically, it only checked for existing
69
+ method definitions for methods that could be directly expressed
70
+ (e.g. not requiring send). Sequel 5 broke the check for setter
71
+ methods that could be directly expressed. This fixes cases where
72
+ model inheritance is used and the setter methods are overridden
73
+ in a parent class.
74
+
75
+ * Alter table emulation now works correctly on SQLite 3.26.0+.
76
+
77
+ * The one_to_one association setter does not modify reciprocal
78
+ associations in cases where doing so is not necessary. This can
79
+ fix some cases where the nested_attributes plugin is used.
80
+
81
+ * The class_table_inheritance plugin can now take advantage of the
82
+ schema_caching extension to prevent database queries to determine
83
+ column information when the class is created.
84
+
85
+ * The nested_attributes plugin no longer validates one_to_one
86
+ associations twice when saving.
87
+
88
+ * The class_table_inheritance plugin :qualify_tables option now
89
+ correctly qualifies subclasses of subclasses.
90
+
91
+ * SQL expressions that are subscripted are now wrapped in parentheses.
92
+ This fixes at least subscripting a function expression on
93
+ PostgreSQL:
94
+
95
+ DB[:t].select{array_agg(column).sql_subscript(1)}
96
+ # SELECT (array_agg(column))[1] FROM t
97
+
98
+ * Sequel::Migrator now uses more descriptive error messages if a
99
+ missing or empty migration directory is given.
100
+
101
+ * bin/sequel -C when converting from SQLite to another database
102
+ type will now use 64-bit integer columns in the other database when
103
+ the SQLite column type is integer, as SQLite supports storing
104
+ 64-bit values in integer columns, and most other databases only
105
+ support 32-bit values in integer columns.
106
+
107
+ = Backwards Compatibility
108
+
109
+ * The mysql adapter no longer attempts to load the mysqlplus driver,
110
+ it now only attempts to load the mysql driver.
@@ -36,6 +36,12 @@ If any other exception is raised, the transaction is rolled back, and the except
36
36
  end # ROLLBACK
37
37
  # ArgumentError raised
38
38
 
39
+ If you want the current transaction to be rolled back when the transaction block exits instead of being committed (even if an exception is not raised), use <tt>Database#rollback_on_exit</tt>
40
+
41
+ DB.transaction do # BEGIN
42
+ DB.rollback_on_exit
43
+ end # ROLLBACK
44
+
39
45
  If you want Sequel::Rollback exceptions to be reraised, use the <tt>rollback: :reraise</tt> option:
40
46
 
41
47
  DB.transaction(rollback: :reraise) do # BEGIN
@@ -121,6 +127,48 @@ Other exceptions, unless rescued inside the outer transaction block, will rollba
121
127
  end # ROLLBACK
122
128
  # ArgumentError raised
123
129
 
130
+ If you want the current savepoint to be rolled back when the savepoint block exits instead of being committed (even if an exception is not raised), use <tt>Database#rollback_on_exit(:savepoint=>true)</tt>
131
+
132
+ DB.transaction do # BEGIN
133
+ DB.transaction(savepoint: true) do # SAVEPOINT
134
+ DB.rollback_on_exit(:savepoint=>true)
135
+ end # ROLLBACK TO SAVEPOINT
136
+ end # COMMIT
137
+
138
+ DB.transaction do # BEGIN
139
+ DB.transaction(savepoint: true) do # SAVEPOINT
140
+ DB.transaction(savepoint: true) do # SAVEPOINT
141
+ DB.rollback_on_exit(:savepoint=>true)
142
+ end # ROLLBACK TO SAVEPOINT
143
+ end # RELEASE SAVEPOINT
144
+ end # COMMIT
145
+
146
+ If you want the current savepoint to be rolled back when the savepoint block exits (even if an exception is not raised), use <tt>Database#rollback_on_exit(:savepoint=>true)</tt>
147
+
148
+ DB.transaction do # BEGIN
149
+ DB.transaction(savepoint: true) do # SAVEPOINT
150
+ DB.rollback_on_exit(:savepoint=>true)
151
+ end # ROLLBACK TO SAVEPOINT
152
+ end # COMMIT
153
+
154
+ If you want the current savepoint and potentially enclosing savepoints to be rolled back when the savepoint blocks exit (even if an exception is not raised), use <tt>Database#rollback_on_exit(:savepoint=>integer)</tt>
155
+
156
+ DB.transaction do # BEGIN
157
+ DB.transaction(savepoint: true) do # SAVEPOINT
158
+ DB.transaction(savepoint: true) do # SAVEPOINT
159
+ DB.rollback_on_exit(:savepoint=>2)
160
+ end # ROLLBACK TO SAVEPOINT
161
+ end # ROLLBACK TO SAVEPOINT
162
+ end # COMMIT
163
+
164
+ DB.transaction do # BEGIN
165
+ DB.transaction(savepoint: true) do # SAVEPOINT
166
+ DB.transaction(savepoint: true) do # SAVEPOINT
167
+ DB.rollback_on_exit(:savepoint=>3)
168
+ end # ROLLBACK TO SAVEPOINT
169
+ end # ROLLBACK TO SAVEPOINT
170
+ end # ROLLBACK
171
+
124
172
  == Prepared Transactions / Two-Phase Commit
125
173
 
126
174
  Sequel supports database prepared transactions on PostgreSQL, MySQL, and H2. With prepared transactions, at the end of the transaction, the transaction is not immediately committed (it acts like a rollback). Later, you can call +commit_prepared_transaction+ to commit the transaction or +rollback_prepared_transaction+ to roll the transaction back. Prepared transactions are usually used with distributed databases to make sure all databases commit the same transaction or none of them do.
@@ -43,17 +43,15 @@ module Sequel
43
43
  true
44
44
  end
45
45
 
46
+ # JDBC savepoint object for the current savepoint for the connection.
47
+ def savepoint_obj(conn)
48
+ _trans(conn)[:savepoints][-1][:obj]
49
+ end
50
+
46
51
  # Use JDBC connection's setAutoCommit to false to start transactions
47
52
  def begin_transaction(conn, opts=OPTS)
48
- if supports_savepoints?
49
- th = _trans(conn)
50
- if sps = th[:savepoint_objs]
51
- sps << log_connection_yield('Transaction.savepoint', conn){conn.set_savepoint}
52
- else
53
- log_connection_yield('Transaction.begin', conn){conn.setAutoCommit(false)}
54
- th[:savepoint_objs] = []
55
- set_transaction_isolation(conn, opts)
56
- end
53
+ if in_savepoint?(conn)
54
+ _trans(conn)[:savepoints][-1][:obj] = log_connection_yield('Transaction.savepoint', conn){conn.set_savepoint}
57
55
  else
58
56
  log_connection_yield('Transaction.begin', conn){conn.setAutoCommit(false)}
59
57
  set_transaction_isolation(conn, opts)
@@ -62,12 +60,9 @@ module Sequel
62
60
 
63
61
  # Use JDBC connection's commit method to commit transactions
64
62
  def commit_transaction(conn, opts=OPTS)
65
- if supports_savepoints?
66
- sps = _trans(conn)[:savepoint_objs]
67
- if sps.empty?
68
- log_connection_yield('Transaction.commit', conn){conn.commit}
69
- elsif supports_releasing_savepoints?
70
- log_connection_yield('Transaction.release_savepoint', conn){supports_releasing_savepoints? ? conn.release_savepoint(sps.last) : sps.last}
63
+ if in_savepoint?(conn)
64
+ if supports_releasing_savepoints?
65
+ log_connection_yield('Transaction.release_savepoint', conn){conn.release_savepoint(savepoint_obj(conn))}
71
66
  end
72
67
  else
73
68
  log_connection_yield('Transaction.commit', conn){conn.commit}
@@ -77,13 +72,9 @@ module Sequel
77
72
  # Use JDBC connection's setAutoCommit to true to enable non-transactional behavior
78
73
  def remove_transaction(conn, committed)
79
74
  if jdbc_level = _trans(conn)[:original_jdbc_isolation_level]
80
- conn.setTransactionIsolation(jdbc_level)
75
+ log_connection_yield("Transaction.restore_isolation_level", conn){conn.setTransactionIsolation(jdbc_level)}
81
76
  end
82
- if supports_savepoints?
83
- sps = _trans(conn)[:savepoint_objs]
84
- conn.setAutoCommit(true) if sps.empty?
85
- sps.pop
86
- else
77
+ unless in_savepoint?(conn)
87
78
  conn.setAutoCommit(true)
88
79
  end
89
80
  ensure
@@ -92,13 +83,8 @@ module Sequel
92
83
 
93
84
  # Use JDBC connection's rollback method to rollback transactions
94
85
  def rollback_transaction(conn, opts=OPTS)
95
- if supports_savepoints?
96
- sps = _trans(conn)[:savepoint_objs]
97
- if sps.empty?
98
- log_connection_yield('Transaction.rollback', conn){conn.rollback}
99
- else
100
- log_connection_yield('Transaction.rollback_savepoint', conn){conn.rollback(sps.last)}
101
- end
86
+ if in_savepoint?(conn)
87
+ log_connection_yield('Transaction.rollback_savepoint', conn){conn.rollback(savepoint_obj(conn))}
102
88
  else
103
89
  log_connection_yield('Transaction.rollback', conn){conn.rollback}
104
90
  end
@@ -1,10 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- begin
4
- require "mysqlplus"
5
- rescue LoadError
6
- require 'mysql'
7
- end
3
+ require 'mysql'
8
4
  raise(LoadError, "require 'mysql' did not define Mysql::CLIENT_MULTI_RESULTS!\n You are probably using the pure ruby mysql.rb driver,\n which Sequel does not support. You need to install\n the C based adapter, and make sure that the mysql.so\n file is loaded instead of the mysql.rb file.\n") unless defined?(Mysql::CLIENT_MULTI_RESULTS)
9
5
 
10
6
  require_relative 'utils/mysql_mysql2'
@@ -21,7 +17,7 @@ module Sequel
21
17
  # Hash with integer keys and callable values for converting MySQL types.
22
18
  MYSQL_TYPES = {}
23
19
  {
24
- [0, 246] => ::BigDecimal.method(:new),
20
+ [0, 246] => ::Kernel.method(:BigDecimal),
25
21
  [2, 3, 8, 9, 13, 247, 248] => tt.method(:integer),
26
22
  [4, 5] => tt.method(:float),
27
23
  [249, 250, 251, 252] => ::Sequel::SQL::Blob.method(:new)
@@ -177,7 +177,10 @@ module Sequel
177
177
  # needed for drop column.
178
178
  def apply_alter_table(table, ops)
179
179
  fks = fetch("PRAGMA foreign_keys")
180
- run "PRAGMA foreign_keys = 0" if fks
180
+ if fks
181
+ run "PRAGMA foreign_keys = 0"
182
+ run "PRAGMA legacy_alter_table = 1" if sqlite_version >= 32600
183
+ end
181
184
  transaction do
182
185
  if ops.length > 1 && ops.all?{|op| op[:op] == :add_constraint || op[:op] == :set_column_null}
183
186
  null_ops, ops = ops.partition{|op| op[:op] == :set_column_null}
@@ -196,7 +199,10 @@ module Sequel
196
199
  end
197
200
  remove_cached_schema(table)
198
201
  ensure
199
- run "PRAGMA foreign_keys = 1" if fks
202
+ if fks
203
+ run "PRAGMA foreign_keys = 1"
204
+ run "PRAGMA legacy_alter_table = 0" if sqlite_version >= 32600
205
+ end
200
206
  end
201
207
 
202
208
  # SQLite supports limited table modification. You can add a column
@@ -725,6 +731,14 @@ module Sequel
725
731
  false
726
732
  end
727
733
 
734
+ # SQLite 3.25+ supports window functions. However, support is only enabled
735
+ # on SQLite 3.26.0+ because internal Sequel usage of window functions
736
+ # to implement eager loading of limited associations triggers
737
+ # an SQLite crash bug in versions 3.25.0-3.25.3.
738
+ def supports_window_functions?
739
+ db.sqlite_version >= 32600
740
+ end
741
+
728
742
  private
729
743
 
730
744
  # SQLite uses string literals instead of identifiers in AS clauses.
@@ -52,7 +52,48 @@ module Sequel
52
52
  end
53
53
  end
54
54
  end
55
-
55
+
56
+ # When exiting the transaction block through methods other than an exception
57
+ # (e.g. normal exit, non-local return, or throw), set the current transaction
58
+ # to rollback instead of committing. This is designed for use in cases where
59
+ # you want to preform a non-local return but also want to rollback instead of
60
+ # committing.
61
+ # Options:
62
+ # :cancel :: Cancel the current rollback_on_exit setting, so exiting will commit instead
63
+ # of rolling back.
64
+ # :savepoint :: Rollback only the current savepoint if inside a savepoint.
65
+ # Can also be an positive integer value to rollback that number of enclosing savepoints,
66
+ # up to and including the transaction itself.
67
+ # If the database does not support savepoints, this option is ignored and the entire
68
+ # transaction is affected.
69
+ # :server :: The server/shard the transaction is being executed on.
70
+ def rollback_on_exit(opts=OPTS)
71
+ synchronize(opts[:server]) do |conn|
72
+ raise Error, "Cannot call Sequel:: Database#rollback_on_exit! unless inside a transaction" unless h = _trans(conn)
73
+ rollback = !opts[:cancel]
74
+
75
+ if supports_savepoints?
76
+ savepoints = h[:savepoints]
77
+
78
+ if level = opts[:savepoint]
79
+ level = 1 if level == true
80
+ raise Error, "invalid :savepoint option to Database#rollback_on_exit: #{level.inspect}" unless level.is_a?(Integer)
81
+ raise Error, "cannot pass nonpositive integer (#{level.inspect}) as :savepoint option to Database#rollback_on_exit" if level < 1
82
+ level.times do |i|
83
+ break unless savepoint = savepoints[-1 - i]
84
+ savepoint[:rollback_on_exit] = rollback
85
+ end
86
+ else
87
+ savepoints[0][:rollback_on_exit] = rollback
88
+ end
89
+ else
90
+ h[:rollback_on_exit] = rollback
91
+ end
92
+ end
93
+
94
+ nil
95
+ end
96
+
56
97
  # Return true if already in a transaction given the options,
57
98
  # false otherwise. Respects the :server option for selecting
58
99
  # a shard.
@@ -164,7 +205,7 @@ module Sequel
164
205
  end
165
206
  end
166
207
 
167
- if opts[:savepoint] != false && (stack = _trans(conn)[:savepoints]) && stack.last
208
+ if opts[:savepoint] != false && (stack = _trans(conn)[:savepoints]) && stack.last[:auto_savepoint]
168
209
  opts[:savepoint] = true
169
210
  end
170
211
 
@@ -242,10 +283,10 @@ module Sequel
242
283
 
243
284
  if supports_savepoints?
244
285
  if t = _trans(conn)
245
- t[:savepoints].push(opts[:auto_savepoint])
286
+ t[:savepoints].push({:auto_savepoint=>opts[:auto_savepoint]})
246
287
  return
247
288
  else
248
- hash[:savepoints] = [opts[:auto_savepoint]]
289
+ hash[:savepoints] = [{:auto_savepoint=>opts[:auto_savepoint]}]
249
290
  if (prep = opts[:prepare]) && supports_prepared_transactions?
250
291
  hash[:prepare] = prep
251
292
  end
@@ -293,12 +334,8 @@ module Sequel
293
334
 
294
335
  # Start a new database transaction or a new savepoint on the given connection.
295
336
  def begin_transaction(conn, opts=OPTS)
296
- if supports_savepoints?
297
- if savepoint_level(conn) > 1
298
- begin_savepoint(conn, opts)
299
- else
300
- begin_new_transaction(conn, opts)
301
- end
337
+ if in_savepoint?(conn)
338
+ begin_savepoint(conn, opts)
302
339
  else
303
340
  begin_new_transaction(conn, opts)
304
341
  end
@@ -318,7 +355,7 @@ module Sequel
318
355
  if exception
319
356
  false
320
357
  else
321
- if Thread.current.status == 'aborting'
358
+ if rollback_on_transaction_exit?(conn, opts)
322
359
  rollback_transaction(conn, opts)
323
360
  false
324
361
  else
@@ -359,10 +396,15 @@ module Sequel
359
396
  []
360
397
  end
361
398
 
399
+ # Whether the connection is currently inside a savepoint.
400
+ def in_savepoint?(conn)
401
+ supports_savepoints? && savepoint_level(conn) > 1
402
+ end
403
+
362
404
  # Retrieve the transaction hooks that should be run for the given
363
405
  # connection and commit status.
364
406
  def transaction_hooks(conn, committed)
365
- if !supports_savepoints? || savepoint_level(conn) == 1
407
+ unless in_savepoint?(conn)
366
408
  _trans(conn)[committed ? :after_commit : :after_rollback]
367
409
  end
368
410
  end
@@ -372,7 +414,7 @@ module Sequel
372
414
  callbacks = transaction_hooks(conn, committed)
373
415
 
374
416
  if transaction_finished?(conn)
375
- h = @transactions[conn]
417
+ h = _trans(conn)
376
418
  rolled_back = !committed
377
419
  Sequel.synchronize{h[:rolled_back] = rolled_back}
378
420
  Sequel.synchronize{@transactions.delete(conn)}
@@ -386,6 +428,17 @@ module Sequel
386
428
  "ROLLBACK TO SAVEPOINT autopoint_#{depth}"
387
429
  end
388
430
 
431
+ # Whether to rollback the transaction when exiting the transaction.
432
+ def rollback_on_transaction_exit?(conn, opts)
433
+ return true if Thread.current.status == 'aborting'
434
+ h = _trans(conn)
435
+ if supports_savepoints?
436
+ h[:savepoints].last[:rollback_on_exit]
437
+ else
438
+ h[:rollback_on_exit]
439
+ end
440
+ end
441
+
389
442
  # Rollback the active transaction on the connection
390
443
  def rollback_transaction(conn, opts=OPTS)
391
444
  if supports_savepoints?