sequel 3.0.0 → 3.1.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 +100 -0
- data/README.rdoc +3 -3
- data/bin/sequel +102 -19
- data/doc/reflection.rdoc +83 -0
- data/doc/release_notes/3.1.0.txt +406 -0
- data/lib/sequel/adapters/ado.rb +11 -0
- data/lib/sequel/adapters/amalgalite.rb +5 -20
- data/lib/sequel/adapters/do.rb +44 -36
- data/lib/sequel/adapters/firebird.rb +29 -43
- data/lib/sequel/adapters/jdbc.rb +17 -27
- data/lib/sequel/adapters/mysql.rb +35 -40
- data/lib/sequel/adapters/odbc.rb +4 -23
- data/lib/sequel/adapters/oracle.rb +22 -19
- data/lib/sequel/adapters/postgres.rb +6 -15
- data/lib/sequel/adapters/shared/mssql.rb +1 -1
- data/lib/sequel/adapters/shared/mysql.rb +29 -10
- data/lib/sequel/adapters/shared/oracle.rb +6 -8
- data/lib/sequel/adapters/shared/postgres.rb +28 -72
- data/lib/sequel/adapters/shared/sqlite.rb +5 -3
- data/lib/sequel/adapters/sqlite.rb +5 -20
- data/lib/sequel/adapters/utils/savepoint_transactions.rb +80 -0
- data/lib/sequel/adapters/utils/unsupported.rb +0 -12
- data/lib/sequel/core.rb +12 -3
- data/lib/sequel/core_sql.rb +1 -8
- data/lib/sequel/database.rb +107 -43
- data/lib/sequel/database/schema_generator.rb +1 -0
- data/lib/sequel/database/schema_methods.rb +38 -4
- data/lib/sequel/dataset.rb +6 -0
- data/lib/sequel/dataset/convenience.rb +2 -2
- data/lib/sequel/dataset/graph.rb +2 -2
- data/lib/sequel/dataset/prepared_statements.rb +3 -8
- data/lib/sequel/dataset/sql.rb +93 -19
- data/lib/sequel/extensions/blank.rb +2 -1
- data/lib/sequel/extensions/inflector.rb +4 -3
- data/lib/sequel/extensions/migration.rb +13 -2
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pretty_table.rb +4 -0
- data/lib/sequel/extensions/query.rb +4 -0
- data/lib/sequel/extensions/schema_dumper.rb +100 -24
- data/lib/sequel/extensions/string_date_time.rb +3 -4
- data/lib/sequel/model.rb +2 -1
- data/lib/sequel/model/associations.rb +96 -38
- data/lib/sequel/model/base.rb +14 -14
- data/lib/sequel/model/plugins.rb +32 -21
- data/lib/sequel/plugins/caching.rb +13 -15
- data/lib/sequel/plugins/identity_map.rb +107 -0
- data/lib/sequel/plugins/lazy_attributes.rb +65 -0
- data/lib/sequel/plugins/many_through_many.rb +188 -0
- data/lib/sequel/plugins/schema.rb +13 -0
- data/lib/sequel/plugins/serialization.rb +53 -37
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
- data/lib/sequel/plugins/validation_class_methods.rb +28 -7
- data/lib/sequel/plugins/validation_helpers.rb +31 -24
- data/lib/sequel/sql.rb +16 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/ado_spec.rb +47 -1
- data/spec/adapters/firebird_spec.rb +39 -36
- data/spec/adapters/mysql_spec.rb +25 -9
- data/spec/adapters/postgres_spec.rb +11 -24
- data/spec/core/database_spec.rb +54 -13
- data/spec/core/dataset_spec.rb +147 -29
- data/spec/core/object_graph_spec.rb +6 -1
- data/spec/core/schema_spec.rb +34 -0
- data/spec/core/spec_helper.rb +0 -2
- data/spec/extensions/caching_spec.rb +7 -0
- data/spec/extensions/identity_map_spec.rb +158 -0
- data/spec/extensions/lazy_attributes_spec.rb +113 -0
- data/spec/extensions/many_through_many_spec.rb +813 -0
- data/spec/extensions/migration_spec.rb +4 -4
- data/spec/extensions/schema_dumper_spec.rb +114 -13
- data/spec/extensions/schema_spec.rb +19 -3
- data/spec/extensions/serialization_spec.rb +28 -0
- data/spec/extensions/single_table_inheritance_spec.rb +25 -1
- data/spec/extensions/spec_helper.rb +2 -7
- data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
- data/spec/extensions/validation_class_methods_spec.rb +10 -5
- data/spec/integration/dataset_test.rb +39 -6
- data/spec/integration/eager_loader_test.rb +7 -7
- data/spec/integration/spec_helper.rb +0 -1
- data/spec/integration/transaction_test.rb +28 -1
- data/spec/model/association_reflection_spec.rb +29 -3
- data/spec/model/associations_spec.rb +1 -0
- data/spec/model/eager_loading_spec.rb +70 -1
- data/spec/model/plugins_spec.rb +236 -50
- data/spec/model/spec_helper.rb +0 -2
- metadata +18 -5
@@ -1,8 +1,10 @@
|
|
1
|
-
Sequel.require 'adapters/utils
|
1
|
+
Sequel.require %w'savepoint_transactions unsupported', 'adapters/utils'
|
2
2
|
|
3
3
|
module Sequel
|
4
4
|
module SQLite
|
5
5
|
module DatabaseMethods
|
6
|
+
include Sequel::Database::SavepointTransactions
|
7
|
+
|
6
8
|
AUTO_VACUUM = [:none, :full, :incremental].freeze
|
7
9
|
PRIMARY_KEY_INDEX_RE = /\Asqlite_autoindex_/.freeze
|
8
10
|
SYNCHRONOUS = [:off, :normal, :full].freeze
|
@@ -199,7 +201,7 @@ module Sequel
|
|
199
201
|
row[:allow_null] = row.delete(:notnull).to_i == 0
|
200
202
|
row[:default] = row.delete(:dflt_value)
|
201
203
|
row[:primary_key] = row.delete(:pk).to_i == 1
|
202
|
-
row[:default] = nil if blank_object?(row[:default])
|
204
|
+
row[:default] = nil if blank_object?(row[:default]) || row[:default] == 'NULL'
|
203
205
|
row[:db_type] = row.delete(:type)
|
204
206
|
row[:type] = schema_column_type(row[:db_type])
|
205
207
|
row
|
@@ -264,7 +266,7 @@ module Sequel
|
|
264
266
|
# Allow inserting of values directly from a dataset.
|
265
267
|
def insert_sql(*values)
|
266
268
|
if (values.size == 1) && values.first.is_a?(Sequel::Dataset)
|
267
|
-
"
|
269
|
+
"#{insert_sql_base}#{source_list(@opts[:from])} #{values.first.sql};"
|
268
270
|
else
|
269
271
|
super(*values)
|
270
272
|
end
|
@@ -83,26 +83,6 @@ module Sequel
|
|
83
83
|
_execute(sql, opts){|conn| conn.get_first_value(sql, opts[:arguments])}
|
84
84
|
end
|
85
85
|
|
86
|
-
# Use the native driver transaction method if there isn't already a transaction
|
87
|
-
# in progress on the connection, always yielding a connection inside a transaction
|
88
|
-
# transaction.
|
89
|
-
def transaction(opts={})
|
90
|
-
synchronize(opts[:server]) do |conn|
|
91
|
-
return yield(conn) if conn.transaction_active?
|
92
|
-
begin
|
93
|
-
result = nil
|
94
|
-
log_info('Transaction.begin')
|
95
|
-
conn.transaction{result = yield(conn)}
|
96
|
-
result
|
97
|
-
rescue ::Exception => e
|
98
|
-
log_info('Transaction.rollback')
|
99
|
-
transaction_error(e, SQLite3::Exception)
|
100
|
-
ensure
|
101
|
-
log_info('Transaction.commit') unless e
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
86
|
private
|
107
87
|
|
108
88
|
# Log the SQL and the arguments, and yield an available connection. Rescue
|
@@ -126,6 +106,11 @@ module Sequel
|
|
126
106
|
o[:max_connections] = 1 if @opts[:database] == ':memory:' || blank_object?(@opts[:database])
|
127
107
|
o
|
128
108
|
end
|
109
|
+
|
110
|
+
# The main error class that SQLite3 raises
|
111
|
+
def database_error_classes
|
112
|
+
[SQLite3::Exception]
|
113
|
+
end
|
129
114
|
|
130
115
|
# Disconnect given connections from the database.
|
131
116
|
def disconnect_connection(c)
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# Module included in adapters that support savepoints, currently MySQL and PostgreSQL.
|
2
|
+
module Sequel
|
3
|
+
class Database
|
4
|
+
module SavepointTransactions
|
5
|
+
SQL_SAVEPOINT = 'SAVEPOINT autopoint_%d'.freeze
|
6
|
+
SQL_ROLLBACK_TO_SAVEPOINT = 'ROLLBACK TO SAVEPOINT autopoint_%d'.freeze
|
7
|
+
SQL_RELEASE_SAVEPOINT = 'RELEASE SAVEPOINT autopoint_%d'.freeze
|
8
|
+
|
9
|
+
# Any adapter that includes this module must support savepoints.
|
10
|
+
def supports_savepoints?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# Don't add the current thread to the list of threads with active
|
17
|
+
# connections if it is already in the list. If there isn't an
|
18
|
+
# active transaction on this thread, set the transaction depth to
|
19
|
+
# zero.
|
20
|
+
def add_transaction
|
21
|
+
th = Thread.current
|
22
|
+
unless @transactions.include?(th)
|
23
|
+
th[:sequel_transaction_depth] = 0
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# If a savepoint is requested, don't reuse an existing transaction
|
29
|
+
def already_in_transaction?(conn, opts)
|
30
|
+
super and !opts[:savepoint]
|
31
|
+
end
|
32
|
+
|
33
|
+
# SQL to start a new savepoint
|
34
|
+
def begin_savepoint_sql(depth)
|
35
|
+
SQL_SAVEPOINT % depth
|
36
|
+
end
|
37
|
+
|
38
|
+
# If there is no active transaction, start a new transaction. Otherwise,
|
39
|
+
# start a savepoint inside the current transaction. Increment the
|
40
|
+
def begin_transaction(conn)
|
41
|
+
th = Thread.current
|
42
|
+
depth = th[:sequel_transaction_depth]
|
43
|
+
conn = transaction_statement_object(conn) if respond_to?(:transaction_statement_object, true)
|
44
|
+
log_connection_execute(conn, depth > 0 ? begin_savepoint_sql(depth) : begin_transaction_sql)
|
45
|
+
th[:sequel_transaction_depth] += 1
|
46
|
+
conn
|
47
|
+
end
|
48
|
+
|
49
|
+
# SQL to commit a savepoint
|
50
|
+
def commit_savepoint_sql(depth)
|
51
|
+
SQL_RELEASE_SAVEPOINT % depth
|
52
|
+
end
|
53
|
+
|
54
|
+
# If currently inside a savepoint, commit/release the savepoint.
|
55
|
+
# Otherwise, commit the transaction.
|
56
|
+
def commit_transaction(conn)
|
57
|
+
depth = Thread.current[:sequel_transaction_depth]
|
58
|
+
log_connection_execute(conn, depth > 1 ? commit_savepoint_sql(depth-1) : commit_transaction_sql)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Decrement the current savepoint/transaction depth
|
62
|
+
def remove_transaction(conn)
|
63
|
+
depth = (Thread.current[:sequel_transaction_depth] -= 1)
|
64
|
+
super unless depth > 0
|
65
|
+
end
|
66
|
+
|
67
|
+
# SQL to rollback to a savepoint
|
68
|
+
def rollback_savepoint_sql(depth)
|
69
|
+
SQL_ROLLBACK_TO_SAVEPOINT % depth
|
70
|
+
end
|
71
|
+
|
72
|
+
# If currently inside a savepoint, rollback to the start of the savepoint.
|
73
|
+
# Otherwise, rollback the entire transaction.
|
74
|
+
def rollback_transaction(conn)
|
75
|
+
depth = Thread.current[:sequel_transaction_depth]
|
76
|
+
log_connection_execute(conn, depth > 1 ? rollback_savepoint_sql(depth-1) : rollback_transaction_sql)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -11,18 +11,6 @@ class Sequel::Dataset
|
|
11
11
|
def intersect(ds, all=false)
|
12
12
|
raise(Sequel::Error, "INTERSECT not supported")
|
13
13
|
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
# Since EXCEPT and INTERSECT are not supported, and order shouldn't matter
|
18
|
-
# when UNION is used, don't worry about parantheses. This may potentially
|
19
|
-
# give incorrect results if UNION ALL is used.
|
20
|
-
def select_compounds_sql(sql)
|
21
|
-
return unless @opts[:compounds]
|
22
|
-
@opts[:compounds].each do |type, dataset, all|
|
23
|
-
sql << " #{type.to_s.upcase}#{' ALL' if all} #{subselect_sql(dataset)}"
|
24
|
-
end
|
25
|
-
end
|
26
14
|
end
|
27
15
|
|
28
16
|
# This module should be included in the dataset class for all databases that
|
data/lib/sequel/core.rb
CHANGED
@@ -118,6 +118,15 @@ module Sequel
|
|
118
118
|
Database.quote_identifiers = value
|
119
119
|
end
|
120
120
|
|
121
|
+
# Load all Sequel extensions given. Only loads extensions included in this
|
122
|
+
# release of Sequel, doesn't load external extensions.
|
123
|
+
#
|
124
|
+
# Sequel.extension(:schema_dumper)
|
125
|
+
# Sequel.extension(:pagination, :query)
|
126
|
+
def self.extension(*extensions)
|
127
|
+
require(extensions, 'extensions')
|
128
|
+
end
|
129
|
+
|
121
130
|
# Require all given files which should be in the same or a subdirectory of
|
122
131
|
# this file. If a subdir is given, assume all files are in that subdir.
|
123
132
|
def self.require(files, subdir=nil)
|
@@ -139,7 +148,7 @@ module Sequel
|
|
139
148
|
begin
|
140
149
|
Date.parse(s, Sequel.convert_two_digit_years)
|
141
150
|
rescue => e
|
142
|
-
raise InvalidValue, "Invalid Date value
|
151
|
+
raise InvalidValue, "Invalid Date value #{s.inspect} (#{e.message})"
|
143
152
|
end
|
144
153
|
end
|
145
154
|
|
@@ -153,7 +162,7 @@ module Sequel
|
|
153
162
|
datetime_class.parse(s)
|
154
163
|
end
|
155
164
|
rescue => e
|
156
|
-
raise InvalidValue, "Invalid #{datetime_class} value
|
165
|
+
raise InvalidValue, "Invalid #{datetime_class} value #{s.inspect} (#{e.message})"
|
157
166
|
end
|
158
167
|
end
|
159
168
|
|
@@ -162,7 +171,7 @@ module Sequel
|
|
162
171
|
begin
|
163
172
|
Time.parse(s)
|
164
173
|
rescue => e
|
165
|
-
raise InvalidValue, "Invalid Time value
|
174
|
+
raise InvalidValue, "Invalid Time value #{s.inspect} (#{e.message})"
|
166
175
|
end
|
167
176
|
end
|
168
177
|
|
data/lib/sequel/core_sql.rb
CHANGED
@@ -210,6 +210,7 @@ class Symbol
|
|
210
210
|
include Sequel::SQL::BooleanMethods
|
211
211
|
include Sequel::SQL::NumericMethods
|
212
212
|
include Sequel::SQL::StringMethods
|
213
|
+
include Sequel::SQL::SubscriptMethods
|
213
214
|
include Sequel::SQL::ComplexExpressionMethods
|
214
215
|
include Sequel::SQL::InequalityMethods if RUBY_VERSION < '1.9.0'
|
215
216
|
|
@@ -237,12 +238,4 @@ class Symbol
|
|
237
238
|
Sequel::SQL::Function.new(self, *args)
|
238
239
|
end
|
239
240
|
alias_method(:[], :sql_function) if RUBY_VERSION < '1.9.0'
|
240
|
-
|
241
|
-
# Return an SQL array subscript with the given arguments.
|
242
|
-
#
|
243
|
-
# :array.sql_subscript(1) # SQL: array[1]
|
244
|
-
# :array.sql_subscript(1, 2) # SQL: array[1, 2]
|
245
|
-
def sql_subscript(*sub)
|
246
|
-
Sequel::SQL::Subscript.new(self, sub.flatten)
|
247
|
-
end
|
248
241
|
end
|
data/lib/sequel/database.rb
CHANGED
@@ -17,11 +17,15 @@ module Sequel
|
|
17
17
|
include Metaprogramming
|
18
18
|
|
19
19
|
# Array of supported database adapters
|
20
|
-
ADAPTERS = %w'ado db2 dbi do firebird informix jdbc mysql odbc openbase oracle postgres sqlite'.collect{|x| x.to_sym}
|
20
|
+
ADAPTERS = %w'ado amalgalite db2 dbi do firebird informix jdbc mysql odbc openbase oracle postgres sqlite'.collect{|x| x.to_sym}
|
21
21
|
|
22
22
|
SQL_BEGIN = 'BEGIN'.freeze
|
23
23
|
SQL_COMMIT = 'COMMIT'.freeze
|
24
24
|
SQL_ROLLBACK = 'ROLLBACK'.freeze
|
25
|
+
|
26
|
+
TRANSACTION_BEGIN = 'Transaction.begin'.freeze
|
27
|
+
TRANSACTION_COMMIT = 'Transaction.commit'.freeze
|
28
|
+
TRANSACTION_ROLLBACK = 'Transaction.rollback'.freeze
|
25
29
|
|
26
30
|
# The identifier input method to use by default
|
27
31
|
@@identifier_input_method = nil
|
@@ -70,7 +74,7 @@ module Sequel
|
|
70
74
|
@opts ||= opts
|
71
75
|
|
72
76
|
@single_threaded = opts.include?(:single_threaded) ? opts[:single_threaded] : @@single_threaded
|
73
|
-
@schemas =
|
77
|
+
@schemas = {}
|
74
78
|
@default_schema = opts.include?(:default_schema) ? opts[:default_schema] : default_schema_default
|
75
79
|
@prepared_statements = {}
|
76
80
|
@transactions = []
|
@@ -438,13 +442,8 @@ module Sequel
|
|
438
442
|
quoted_name = quote_schema_table(table)
|
439
443
|
opts = opts.merge(:schema=>sch) if sch && !opts.include?(:schema)
|
440
444
|
|
441
|
-
@schemas.delete(quoted_name) if opts[:reload]
|
442
|
-
return @schemas[quoted_name] if @schemas
|
443
|
-
|
444
|
-
@schemas ||= Hash.new do |h,k|
|
445
|
-
quote_name = quote_schema_table(k)
|
446
|
-
h[quote_name] if h.include?(quote_name)
|
447
|
-
end
|
445
|
+
@schemas.delete(quoted_name) if opts[:reload]
|
446
|
+
return @schemas[quoted_name] if @schemas[quoted_name]
|
448
447
|
|
449
448
|
cols = schema_parse_table(table_name, opts)
|
450
449
|
raise(Error, 'schema parsing returned no columns, table probably doesn\'t exist') if cols.nil? || cols.empty?
|
@@ -460,20 +459,21 @@ module Sequel
|
|
460
459
|
def synchronize(server=nil, &block)
|
461
460
|
@pool.hold(server || :default, &block)
|
462
461
|
end
|
462
|
+
|
463
|
+
# Whether the database and adapter support savepoints
|
464
|
+
def supports_savepoints?
|
465
|
+
false
|
466
|
+
end
|
463
467
|
|
464
468
|
# Returns true if a table with the given name exists. This requires a query
|
465
469
|
# to the database unless this database object already has the schema for
|
466
470
|
# the given table name.
|
467
471
|
def table_exists?(name)
|
468
|
-
|
472
|
+
begin
|
473
|
+
from(name).first
|
469
474
|
true
|
470
|
-
|
471
|
-
|
472
|
-
from(name).first
|
473
|
-
true
|
474
|
-
rescue
|
475
|
-
false
|
476
|
-
end
|
475
|
+
rescue
|
476
|
+
false
|
477
477
|
end
|
478
478
|
end
|
479
479
|
|
@@ -484,29 +484,21 @@ module Sequel
|
|
484
484
|
true
|
485
485
|
end
|
486
486
|
|
487
|
-
#
|
488
|
-
#
|
489
|
-
#
|
490
|
-
#
|
491
|
-
|
487
|
+
# Starts a database transaction. When a database transaction is used,
|
488
|
+
# either all statements are successful or none of the statements are
|
489
|
+
# successful. Note that MySQL MyISAM tabels do not support transactions.
|
490
|
+
#
|
491
|
+
# The following options are respected:
|
492
|
+
#
|
493
|
+
# * :server - The server to use for the transaction
|
494
|
+
# * :savepoint - Whether to create a new savepoint for this transaction,
|
495
|
+
# only respected if the database adapter supports savepoints. By
|
496
|
+
# default Sequel will reuse an existing transaction, so if you want to
|
497
|
+
# use a savepoint you must use this option.
|
498
|
+
def transaction(opts={}, &block)
|
492
499
|
synchronize(opts[:server]) do |conn|
|
493
|
-
return yield(conn) if
|
494
|
-
|
495
|
-
conn.execute(begin_transaction_sql)
|
496
|
-
begin
|
497
|
-
@transactions << Thread.current
|
498
|
-
yield(conn)
|
499
|
-
rescue Exception => e
|
500
|
-
log_info(rollback_transaction_sql)
|
501
|
-
conn.execute(rollback_transaction_sql)
|
502
|
-
transaction_error(e)
|
503
|
-
ensure
|
504
|
-
unless e
|
505
|
-
log_info(commit_transaction_sql)
|
506
|
-
conn.execute(commit_transaction_sql)
|
507
|
-
end
|
508
|
-
@transactions.delete(Thread.current)
|
509
|
-
end
|
500
|
+
return yield(conn) if already_in_transaction?(conn, opts)
|
501
|
+
_transaction(conn, &block)
|
510
502
|
end
|
511
503
|
end
|
512
504
|
|
@@ -554,6 +546,45 @@ module Sequel
|
|
554
546
|
|
555
547
|
private
|
556
548
|
|
549
|
+
# Internal generic transaction method. Any exception raised by the given
|
550
|
+
# block will cause the transaction to be rolled back. If the exception is
|
551
|
+
# not Sequel::Rollback, the error will be reraised. If no exception occurs
|
552
|
+
# inside the block, the transaction is commited.
|
553
|
+
def _transaction(conn)
|
554
|
+
begin
|
555
|
+
add_transaction
|
556
|
+
t = begin_transaction(conn)
|
557
|
+
yield(conn)
|
558
|
+
rescue Exception => e
|
559
|
+
rollback_transaction(t)
|
560
|
+
transaction_error(e)
|
561
|
+
ensure
|
562
|
+
begin
|
563
|
+
commit_transaction(t) unless e
|
564
|
+
rescue Exception => e
|
565
|
+
raise_error(e, :classes=>database_error_classes)
|
566
|
+
ensure
|
567
|
+
remove_transaction(t)
|
568
|
+
end
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
# Add the current thread to the list of active transactions
|
573
|
+
def add_transaction
|
574
|
+
@transactions << Thread.current
|
575
|
+
end
|
576
|
+
|
577
|
+
# Whether the current thread/connection is already inside a transaction
|
578
|
+
def already_in_transaction?(conn, opts)
|
579
|
+
@transactions.include?(Thread.current)
|
580
|
+
end
|
581
|
+
|
582
|
+
# Start a new database transaction on the given connection.
|
583
|
+
def begin_transaction(conn)
|
584
|
+
log_connection_execute(conn, begin_transaction_sql)
|
585
|
+
conn
|
586
|
+
end
|
587
|
+
|
557
588
|
# SQL to BEGIN a transaction.
|
558
589
|
def begin_transaction_sql
|
559
590
|
SQL_BEGIN
|
@@ -576,17 +607,33 @@ module Sequel
|
|
576
607
|
obj.respond_to?(:empty?) ? obj.empty? : false
|
577
608
|
end
|
578
609
|
end
|
610
|
+
|
611
|
+
# Commit the active transaction on the connection
|
612
|
+
def commit_transaction(conn)
|
613
|
+
log_connection_execute(conn, commit_transaction_sql)
|
614
|
+
end
|
579
615
|
|
580
616
|
# SQL to COMMIT a transaction.
|
581
617
|
def commit_transaction_sql
|
582
618
|
SQL_COMMIT
|
583
619
|
end
|
620
|
+
|
621
|
+
# Method called on the connection object to execute SQL on the database,
|
622
|
+
# used by the transaction code.
|
623
|
+
def connection_execute_method
|
624
|
+
:execute
|
625
|
+
end
|
584
626
|
|
585
627
|
# The default options for the connection pool.
|
586
628
|
def connection_pool_default_options
|
587
629
|
{}
|
588
630
|
end
|
589
631
|
|
632
|
+
# Which transaction errors to translate, blank by default.
|
633
|
+
def database_error_classes
|
634
|
+
[]
|
635
|
+
end
|
636
|
+
|
590
637
|
# The default value for default_schema.
|
591
638
|
def default_schema_default
|
592
639
|
nil
|
@@ -614,6 +661,13 @@ module Sequel
|
|
614
661
|
def input_identifier_meth
|
615
662
|
dataset.method(:input_identifier)
|
616
663
|
end
|
664
|
+
|
665
|
+
# Log the given SQL and then execute it on the connection, used by
|
666
|
+
# the transaction code.
|
667
|
+
def log_connection_execute(conn, sql)
|
668
|
+
log_info(sql)
|
669
|
+
conn.send(connection_execute_method, sql)
|
670
|
+
end
|
617
671
|
|
618
672
|
# Return a dataset that uses the default identifier input and output methods
|
619
673
|
# for this database. Used when parsing metadata so that column symbols are
|
@@ -648,7 +702,7 @@ module Sequel
|
|
648
702
|
# and traceback.
|
649
703
|
def raise_error(exception, opts={})
|
650
704
|
if !opts[:classes] || Array(opts[:classes]).any?{|c| exception.is_a?(c)}
|
651
|
-
e = DatabaseError.new("#{exception.class} #{exception.message}")
|
705
|
+
e = (opts[:disconnect] ? DatabaseDisconnectError : DatabaseError).new("#{exception.class}: #{exception.message}")
|
652
706
|
e.set_backtrace(exception.backtrace)
|
653
707
|
raise e
|
654
708
|
else
|
@@ -660,12 +714,22 @@ module Sequel
|
|
660
714
|
def remove_cached_schema(table)
|
661
715
|
@schemas.delete(quote_schema_table(table)) if @schemas
|
662
716
|
end
|
717
|
+
|
718
|
+
# Remove the current thread from the list of active transactions
|
719
|
+
def remove_transaction(conn)
|
720
|
+
@transactions.delete(Thread.current)
|
721
|
+
end
|
663
722
|
|
664
723
|
# Remove the cached schema_utility_dataset, because the identifier
|
665
724
|
# quoting has changed.
|
666
725
|
def reset_schema_utility_dataset
|
667
726
|
@schema_utility_dataset = nil
|
668
727
|
end
|
728
|
+
|
729
|
+
# Rollback the active transaction on the connection
|
730
|
+
def rollback_transaction(conn)
|
731
|
+
log_connection_execute(conn, rollback_transaction_sql)
|
732
|
+
end
|
669
733
|
|
670
734
|
# Split the schema information from the table
|
671
735
|
def schema_and_table(table_name)
|
@@ -686,7 +750,7 @@ module Sequel
|
|
686
750
|
Sequel.convert_tinyint_to_bool ? :boolean : :integer
|
687
751
|
when /\Ainterval\z/io
|
688
752
|
:interval
|
689
|
-
when /\A(character( varying)?|
|
753
|
+
when /\A(character( varying)?|(var)?char|text)/io
|
690
754
|
:string
|
691
755
|
when /\A(int(eger)?|bigint|smallint)/io
|
692
756
|
:integer
|
@@ -733,8 +797,8 @@ module Sequel
|
|
733
797
|
end
|
734
798
|
|
735
799
|
# Raise a database error unless the exception is an Rollback.
|
736
|
-
def transaction_error(e
|
737
|
-
raise_error(e, :classes=>
|
800
|
+
def transaction_error(e)
|
801
|
+
raise_error(e, :classes=>database_error_classes) unless Rollback === e
|
738
802
|
end
|
739
803
|
|
740
804
|
# Typecast the value to an SQL::Blob
|