sequel 4.38.0 → 4.39.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +28 -0
- data/doc/association_basics.rdoc +1 -1
- data/doc/core_extensions.rdoc +8 -8
- data/doc/object_model.rdoc +7 -8
- data/doc/querying.rdoc +2 -2
- data/doc/release_notes/4.39.0.txt +127 -0
- data/doc/sql.rdoc +31 -31
- data/doc/transactions.rdoc +1 -1
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/mock.rb +22 -66
- data/lib/sequel/adapters/shared/access.rb +2 -0
- data/lib/sequel/adapters/shared/cubrid.rb +2 -0
- data/lib/sequel/adapters/shared/db2.rb +2 -0
- data/lib/sequel/adapters/shared/firebird.rb +2 -0
- data/lib/sequel/adapters/shared/informix.rb +2 -0
- data/lib/sequel/adapters/shared/mssql.rb +10 -2
- data/lib/sequel/adapters/shared/mysql.rb +17 -4
- data/lib/sequel/adapters/shared/oracle.rb +9 -0
- data/lib/sequel/adapters/shared/postgres.rb +34 -1
- data/lib/sequel/adapters/shared/sqlanywhere.rb +1 -0
- data/lib/sequel/adapters/shared/sqlite.rb +8 -0
- data/lib/sequel/core.rb +10 -0
- data/lib/sequel/database.rb +5 -0
- data/lib/sequel/database/connecting.rb +28 -0
- data/lib/sequel/database/misc.rb +0 -51
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +9 -0
- data/lib/sequel/database/transactions.rb +65 -0
- data/lib/sequel/dataset/actions.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +1 -1
- data/lib/sequel/extensions/core_extensions.rb +1 -1
- data/lib/sequel/extensions/core_refinements.rb +1 -1
- data/lib/sequel/extensions/migration.rb +17 -1
- data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/pg_array_ops.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +1 -1
- data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
- data/lib/sequel/extensions/pg_interval.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +28 -15
- data/lib/sequel/extensions/pg_range_ops.rb +1 -1
- data/lib/sequel/extensions/pg_row_ops.rb +1 -1
- data/lib/sequel/extensions/select_remove.rb +1 -1
- data/lib/sequel/extensions/sql_expr.rb +1 -1
- data/lib/sequel/model/associations.rb +1 -1
- data/lib/sequel/plugins/active_model.rb +19 -8
- data/lib/sequel/plugins/dataset_associations.rb +1 -1
- data/lib/sequel/plugins/hook_class_methods.rb +38 -2
- data/lib/sequel/plugins/list.rb +1 -1
- data/lib/sequel/plugins/pg_array_associations.rb +3 -3
- data/lib/sequel/plugins/timestamps.rb +15 -2
- data/lib/sequel/plugins/touch.rb +6 -0
- data/lib/sequel/sql.rb +15 -11
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +18 -0
- data/spec/adapters/postgres_spec.rb +30 -1
- data/spec/core/database_spec.rb +29 -0
- data/spec/core/mock_adapter_spec.rb +32 -1
- data/spec/extensions/migration_spec.rb +46 -0
- data/spec/extensions/pg_interval_spec.rb +1 -0
- data/spec/extensions/pg_json_ops_spec.rb +13 -0
- data/spec/extensions/timestamps_spec.rb +11 -0
- data/spec/extensions/touch_spec.rb +8 -0
- metadata +4 -2
data/doc/transactions.rdoc
CHANGED
@@ -168,4 +168,4 @@ behavior to execute multiple times. For example, with the following code:
|
|
168
168
|
|
169
169
|
The logger.info method will be called multiple times if there is a serialization failure.
|
170
170
|
|
171
|
-
The :num_retries option can be used to set the
|
171
|
+
The :num_retries option can be used to set the maximum number of times to retry. It is set to 5 times by default.
|
data/doc/virtual_rows.rdoc
CHANGED
@@ -23,7 +23,7 @@ SQL function expression.
|
|
23
23
|
It's possible to use Sequel's DSL to represent such expressions, but it is a
|
24
24
|
little verbose:
|
25
25
|
|
26
|
-
dataset.where(Sequel
|
26
|
+
dataset.where(Sequel[:a] > Sequel.function(:b, :c))
|
27
27
|
# WHERE a > b(c)
|
28
28
|
|
29
29
|
The virtual row DSL makes such code more concise:
|
data/lib/sequel/adapters/mock.rb
CHANGED
@@ -32,63 +32,6 @@ module Sequel
|
|
32
32
|
class Database < Sequel::Database
|
33
33
|
set_adapter_scheme :mock
|
34
34
|
|
35
|
-
# Map of database type names to module names, used for handling
|
36
|
-
# mock adapters for specific database types.
|
37
|
-
SHARED_ADAPTERS = {
|
38
|
-
'access'=>'Access',
|
39
|
-
'cubrid'=>'Cubrid',
|
40
|
-
'db2'=>'DB2',
|
41
|
-
'firebird'=>'Firebird',
|
42
|
-
'informix'=>'Informix',
|
43
|
-
'mssql'=>'MSSQL',
|
44
|
-
'mysql'=>'MySQL',
|
45
|
-
'oracle'=>'Oracle',
|
46
|
-
'postgres'=>'Postgres',
|
47
|
-
'sqlanywhere'=>'SqlAnywhere',
|
48
|
-
'sqlite'=>'SQLite'
|
49
|
-
}
|
50
|
-
|
51
|
-
# Procs to run for specific database types to get the mock adapter
|
52
|
-
# to work with the shared adapter
|
53
|
-
SHARED_ADAPTER_SETUP = {
|
54
|
-
'postgres' => lambda do |db|
|
55
|
-
db.instance_eval do
|
56
|
-
@server_version = 90500
|
57
|
-
initialize_postgres_adapter
|
58
|
-
end
|
59
|
-
db.extend(Module.new do
|
60
|
-
def bound_variable_arg(arg, conn)
|
61
|
-
arg
|
62
|
-
end
|
63
|
-
|
64
|
-
def primary_key(table)
|
65
|
-
:id
|
66
|
-
end
|
67
|
-
end)
|
68
|
-
end,
|
69
|
-
'oracle' => lambda do |db|
|
70
|
-
db.instance_eval do
|
71
|
-
@server_version = 11000000
|
72
|
-
@primary_key_sequences = {}
|
73
|
-
end
|
74
|
-
end,
|
75
|
-
'mysql' => lambda do |db|
|
76
|
-
db.instance_eval do
|
77
|
-
@server_version = 50617
|
78
|
-
end
|
79
|
-
end,
|
80
|
-
'mssql' => lambda do |db|
|
81
|
-
db.instance_eval do
|
82
|
-
@server_version = 11000000
|
83
|
-
end
|
84
|
-
end,
|
85
|
-
'sqlite' => lambda do |db|
|
86
|
-
db.instance_eval do
|
87
|
-
@sqlite_version = 30903
|
88
|
-
end
|
89
|
-
end
|
90
|
-
}
|
91
|
-
|
92
35
|
# Set the autogenerated primary key integer
|
93
36
|
# to be returned when running an insert query.
|
94
37
|
# Argument types supported:
|
@@ -292,17 +235,30 @@ module Sequel
|
|
292
235
|
def adapter_initialize
|
293
236
|
opts = @opts
|
294
237
|
@sqls = opts[:sqls] || []
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
238
|
+
@shared_adapter = false
|
239
|
+
|
240
|
+
case db_type = opts[:host]
|
241
|
+
when String, Symbol
|
242
|
+
db_type = db_type.to_sym
|
243
|
+
unless mod = Sequel.synchronize{SHARED_ADAPTER_MAP[db_type]}
|
244
|
+
begin
|
245
|
+
require "sequel/adapters/shared/#{db_type}"
|
246
|
+
rescue LoadError
|
247
|
+
else
|
248
|
+
mod = Sequel.synchronize{SHARED_ADAPTER_MAP[db_type]}
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
if mod
|
253
|
+
@shared_adapter = true
|
254
|
+
extend(mod::DatabaseMethods)
|
255
|
+
extend_datasets(mod::DatasetMethods)
|
256
|
+
if mod.respond_to?(:mock_adapter_setup)
|
257
|
+
mod.mock_adapter_setup(self)
|
258
|
+
end
|
302
259
|
end
|
303
|
-
else
|
304
|
-
@shared_adapter = false
|
305
260
|
end
|
261
|
+
|
306
262
|
self.autoid = opts[:autoid]
|
307
263
|
self.columns = opts[:columns]
|
308
264
|
self.fetch = opts[:fetch]
|
@@ -5,6 +5,14 @@ Sequel.require %w'emulate_offset_with_row_number split_alter_table', 'adapters/u
|
|
5
5
|
module Sequel
|
6
6
|
Dataset::NON_SQL_OPTIONS << :disable_insert_output
|
7
7
|
module MSSQL
|
8
|
+
Sequel::Database.set_shared_adapter_scheme(:mssql, self)
|
9
|
+
|
10
|
+
def self.mock_adapter_setup(db)
|
11
|
+
db.instance_eval do
|
12
|
+
@server_version = 11000000
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
8
16
|
module DatabaseMethods
|
9
17
|
extend Sequel::Database::ResetIdentifierMangling
|
10
18
|
|
@@ -433,8 +441,8 @@ module Sequel
|
|
433
441
|
tn = m2.call(table_name.to_s)
|
434
442
|
table_id = get(Sequel.function(:object_id, tn))
|
435
443
|
info_sch_sch = opts[:information_schema_schema]
|
436
|
-
inf_sch_qual = lambda{|s| info_sch_sch ? Sequel.qualify(info_sch_sch, s) : Sequel
|
437
|
-
sys_qual = lambda{|s| info_sch_sch ? Sequel.qualify(info_sch_sch, Sequel.qualify(Sequel.lit(''), s)) : Sequel
|
444
|
+
inf_sch_qual = lambda{|s| info_sch_sch ? Sequel.qualify(info_sch_sch, s) : Sequel[s]}
|
445
|
+
sys_qual = lambda{|s| info_sch_sch ? Sequel.qualify(info_sch_sch, Sequel.qualify(Sequel.lit(''), s)) : Sequel[s]}
|
438
446
|
|
439
447
|
identity_cols = metadata_dataset.from(Sequel.lit('[sys].[columns]')).
|
440
448
|
where(:object_id=>table_id, :is_identity=>true).
|
@@ -9,6 +9,14 @@ module Sequel
|
|
9
9
|
Dataset::NON_SQL_OPTIONS << :on_duplicate_key_update
|
10
10
|
|
11
11
|
module MySQL
|
12
|
+
Sequel::Database.set_shared_adapter_scheme(:mysql, self)
|
13
|
+
|
14
|
+
def self.mock_adapter_setup(db)
|
15
|
+
db.instance_eval do
|
16
|
+
@server_version = 50617
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
12
20
|
@convert_tinyint_to_bool = true
|
13
21
|
|
14
22
|
class << self
|
@@ -188,17 +196,22 @@ module Sequel
|
|
188
196
|
private
|
189
197
|
|
190
198
|
def alter_table_add_column_sql(table, op)
|
191
|
-
if
|
192
|
-
|
199
|
+
pos = if after_col = op[:after]
|
200
|
+
" AFTER #{quote_identifier(after_col)}"
|
201
|
+
elsif op[:first]
|
202
|
+
" FIRST"
|
203
|
+
end
|
204
|
+
|
205
|
+
sql = if related = op.delete(:table)
|
206
|
+
sql = super + "#{pos}, ADD "
|
193
207
|
op[:table] = related
|
194
208
|
op[:key] ||= primary_key_from_schema(related)
|
195
|
-
sql << ", ADD "
|
196
209
|
if constraint_name = op.delete(:foreign_key_constraint_name)
|
197
210
|
sql << "CONSTRAINT #{quote_identifier(constraint_name)} "
|
198
211
|
end
|
199
212
|
sql << "FOREIGN KEY (#{quote_identifier(op[:name])})#{column_references_sql(op)}"
|
200
213
|
else
|
201
|
-
super
|
214
|
+
"#{super}#{pos}"
|
202
215
|
end
|
203
216
|
end
|
204
217
|
|
@@ -4,6 +4,15 @@ Sequel.require 'adapters/utils/emulate_offset_with_row_number'
|
|
4
4
|
|
5
5
|
module Sequel
|
6
6
|
module Oracle
|
7
|
+
Sequel::Database.set_shared_adapter_scheme(:oracle, self)
|
8
|
+
|
9
|
+
def self.mock_adapter_setup(db)
|
10
|
+
db.instance_eval do
|
11
|
+
@server_version = 11000000
|
12
|
+
@primary_key_sequences = {}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
7
16
|
module DatabaseMethods
|
8
17
|
extend Sequel::Database::ResetIdentifierMangling
|
9
18
|
|
@@ -25,6 +25,26 @@ module Sequel
|
|
25
25
|
# qualification, and in which order to check the schemas when
|
26
26
|
# an unqualified object is referenced.
|
27
27
|
module Postgres
|
28
|
+
Sequel::Database.set_shared_adapter_scheme(:postgres, self)
|
29
|
+
|
30
|
+
module MockAdapterDatabaseMethods
|
31
|
+
def bound_variable_arg(arg, conn)
|
32
|
+
arg
|
33
|
+
end
|
34
|
+
|
35
|
+
def primary_key(table)
|
36
|
+
:id
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.mock_adapter_setup(db)
|
41
|
+
db.instance_eval do
|
42
|
+
@server_version = 90500
|
43
|
+
initialize_postgres_adapter
|
44
|
+
extend(MockAdapterDatabaseMethods)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
28
48
|
# Array of exceptions that need to be converted. JDBC
|
29
49
|
# uses NativeExceptions, the native adapter uses PGError.
|
30
50
|
CONVERTED_EXCEPTIONS = []
|
@@ -577,6 +597,10 @@ module Sequel
|
|
577
597
|
end
|
578
598
|
end
|
579
599
|
|
600
|
+
def alter_table_add_column_sql(table, op)
|
601
|
+
"ADD COLUMN#{' IF NOT EXISTS' if op[:if_not_exists]} #{column_definition_sql(op)}"
|
602
|
+
end
|
603
|
+
|
580
604
|
# Use a PostgreSQL-specific alter table generator
|
581
605
|
def alter_table_generator_class
|
582
606
|
Postgres::AlterTableGenerator
|
@@ -1315,6 +1339,8 @@ module Sequel
|
|
1315
1339
|
# :phrase :: Similar to :plain, but also adding an ILIKE filter to ensure that
|
1316
1340
|
# returned rows also include the exact phrase used.
|
1317
1341
|
# :rank :: Set to true to order by the rank, so that closer matches are returned first.
|
1342
|
+
# :to_tsquery :: Can be set to :plain or :phrase to specify the function to use to
|
1343
|
+
# convert the terms to a ts_query.
|
1318
1344
|
# :tsquery :: Specifies the terms argument is already a valid SQL expression returning a
|
1319
1345
|
# tsquery, and can be used directly in the query.
|
1320
1346
|
# :tsvector :: Specifies the cols argument is already a valid SQL expression returning a
|
@@ -1329,7 +1355,14 @@ module Sequel
|
|
1329
1355
|
|
1330
1356
|
unless opts[:tsquery]
|
1331
1357
|
phrase_terms = terms.is_a?(Array) ? terms.join(' | ') : terms
|
1332
|
-
|
1358
|
+
|
1359
|
+
query_func = case to_tsquery = opts[:to_tsquery]
|
1360
|
+
when :phrase, :plain
|
1361
|
+
:"#{to_tsquery}to_tsquery"
|
1362
|
+
else
|
1363
|
+
(opts[:phrase] || opts[:plain]) ? :plainto_tsquery : :to_tsquery
|
1364
|
+
end
|
1365
|
+
|
1333
1366
|
terms = Sequel.function(query_func, lang, phrase_terms)
|
1334
1367
|
end
|
1335
1368
|
|
@@ -4,6 +4,14 @@ Sequel.require 'adapters/utils/replace'
|
|
4
4
|
|
5
5
|
module Sequel
|
6
6
|
module SQLite
|
7
|
+
Sequel::Database.set_shared_adapter_scheme(:sqlite, self)
|
8
|
+
|
9
|
+
def self.mock_adapter_setup(db)
|
10
|
+
db.instance_eval do
|
11
|
+
@sqlite_version = 30903
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
7
15
|
# No matter how you connect to SQLite, the following Database options
|
8
16
|
# can be used to set PRAGMAs on connections in a thread-safe manner:
|
9
17
|
# :auto_vacuum, :foreign_keys, :synchronous, and :temp_store.
|
data/lib/sequel/core.rb
CHANGED
@@ -392,6 +392,16 @@ module Sequel
|
|
392
392
|
|
393
393
|
require(%w"deprecated sql connection_pool exceptions dataset database timezones ast_transformer version")
|
394
394
|
|
395
|
+
class << self
|
396
|
+
# Allow nicer syntax for creating Sequel expressions:
|
397
|
+
#
|
398
|
+
# Sequel[1] # => Sequel::SQL::NumericExpression: 1
|
399
|
+
# Sequel["a"] # => Sequel::SQL::StringExpression: 'a'
|
400
|
+
# Sequel[:a] # => Sequel::SQL::Identifier: "a"
|
401
|
+
# Sequel[:a=>1] # => Sequel::SQL::BooleanExpression: ("a" = 1)
|
402
|
+
alias_method :[], :expr
|
403
|
+
end
|
404
|
+
|
395
405
|
# Add the database adapter class methods to Sequel via metaprogramming
|
396
406
|
def_adapter_method(*Database::ADAPTERS)
|
397
407
|
end
|
data/lib/sequel/database.rb
CHANGED
@@ -5,6 +5,11 @@ module Sequel
|
|
5
5
|
# symbol, and the value is the Database subclass.
|
6
6
|
ADAPTER_MAP = {}
|
7
7
|
|
8
|
+
# Hash of shared adapters that have been registered. The key is the
|
9
|
+
# adapter scheme symbol, and the value is the Sequel module containing
|
10
|
+
# the shared adapter.
|
11
|
+
SHARED_ADAPTER_MAP = {}
|
12
|
+
|
8
13
|
# Array of all databases to which Sequel has connected. If you are
|
9
14
|
# developing an application that can connect to an arbitrary number of
|
10
15
|
# databases, delete the database objects from this or they will not get
|
@@ -129,6 +129,34 @@ module Sequel
|
|
129
129
|
Sequel.synchronize{ADAPTER_MAP[scheme] = self}
|
130
130
|
end
|
131
131
|
private_class_method :set_adapter_scheme
|
132
|
+
|
133
|
+
# Sets the given module as the shared adapter module for the given scheme.
|
134
|
+
# Used to register shared adapters for use by the mock adapter. Example:
|
135
|
+
#
|
136
|
+
# # in file sequel/adapters/shared/mydb.rb
|
137
|
+
# module Sequel::MyDB
|
138
|
+
# Sequel::Database.set_shared_adapter_scheme :mydb, :self
|
139
|
+
#
|
140
|
+
# def self.mock_adapter_setup(db)
|
141
|
+
# # ...
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# module DatabaseMethods
|
145
|
+
# # ...
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# module DatasetMethods
|
149
|
+
# # ...
|
150
|
+
# end
|
151
|
+
# end
|
152
|
+
#
|
153
|
+
# would allow the mock adapter to return a Database instance that supports
|
154
|
+
# the MyDB syntax via:
|
155
|
+
#
|
156
|
+
# Sequel.connect('mock://mydb')
|
157
|
+
def self.set_shared_adapter_scheme(scheme, mod)
|
158
|
+
Sequel.synchronize{SHARED_ADAPTER_MAP[scheme] = mod}
|
159
|
+
end
|
132
160
|
|
133
161
|
# The connection pool for this Database instance. All Database instances have
|
134
162
|
# their own connection pools.
|
data/lib/sequel/database/misc.rb
CHANGED
@@ -160,38 +160,6 @@ module Sequel
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
-
# If a transaction is not currently in process, yield to the block immediately.
|
164
|
-
# Otherwise, add the block to the list of blocks to call after the currently
|
165
|
-
# in progress transaction commits (and only if it commits).
|
166
|
-
# Options:
|
167
|
-
# :server :: The server/shard to use.
|
168
|
-
def after_commit(opts=OPTS, &block)
|
169
|
-
raise Error, "must provide block to after_commit" unless block
|
170
|
-
synchronize(opts[:server]) do |conn|
|
171
|
-
if h = _trans(conn)
|
172
|
-
raise Error, "cannot call after_commit in a prepared transaction" if h[:prepare]
|
173
|
-
add_transaction_hook(conn, :after_commit, block)
|
174
|
-
else
|
175
|
-
yield
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
# If a transaction is not currently in progress, ignore the block.
|
181
|
-
# Otherwise, add the block to the list of the blocks to call after the currently
|
182
|
-
# in progress transaction rolls back (and only if it rolls back).
|
183
|
-
# Options:
|
184
|
-
# :server :: The server/shard to use.
|
185
|
-
def after_rollback(opts=OPTS, &block)
|
186
|
-
raise Error, "must provide block to after_rollback" unless block
|
187
|
-
synchronize(opts[:server]) do |conn|
|
188
|
-
if h = _trans(conn)
|
189
|
-
raise Error, "cannot call after_rollback in a prepared transaction" if h[:prepare]
|
190
|
-
add_transaction_hook(conn, :after_rollback, block)
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
163
|
# Cast the given type to a literal type
|
196
164
|
#
|
197
165
|
# DB.cast_type_literal(Float) # double precision
|
@@ -224,13 +192,6 @@ module Sequel
|
|
224
192
|
Sequel.convert_output_timestamp(v, timezone)
|
225
193
|
end
|
226
194
|
|
227
|
-
# Return true if already in a transaction given the options,
|
228
|
-
# false otherwise. Respects the :server option for selecting
|
229
|
-
# a shard.
|
230
|
-
def in_transaction?(opts=OPTS)
|
231
|
-
synchronize(opts[:server]){|conn| !!_trans(conn)}
|
232
|
-
end
|
233
|
-
|
234
195
|
# Returns a string representation of the database object including the
|
235
196
|
# class name and connection URI and options used when connecting (if any).
|
236
197
|
def inspect
|
@@ -341,13 +302,6 @@ module Sequel
|
|
341
302
|
def adapter_initialize
|
342
303
|
end
|
343
304
|
|
344
|
-
# Set the given callable as a hook to be called. Type should be either
|
345
|
-
# :after_commit or :after_rollback.
|
346
|
-
def add_transaction_hook(conn, type, block)
|
347
|
-
hooks = _trans(conn)[type] ||= []
|
348
|
-
hooks << block
|
349
|
-
end
|
350
|
-
|
351
305
|
# Returns true when the object is considered blank.
|
352
306
|
# The only objects that are blank are nil, false,
|
353
307
|
# strings with all whitespace, and ones that respond
|
@@ -366,11 +320,6 @@ module Sequel
|
|
366
320
|
end
|
367
321
|
end
|
368
322
|
|
369
|
-
# Which transaction errors to translate, blank by default.
|
370
|
-
def database_error_classes
|
371
|
-
[]
|
372
|
-
end
|
373
|
-
|
374
323
|
# An enumerable yielding pairs of regexps and exception classes, used
|
375
324
|
# to match against underlying driver exception messages in
|
376
325
|
# order to raise a more specific Sequel::DatabaseError subclass.
|