sequel 3.0.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|