sequel 3.40.0 → 3.41.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 +40 -0
- data/README.rdoc +2 -2
- data/doc/advanced_associations.rdoc +12 -0
- data/doc/bin_sequel.rdoc +144 -0
- data/doc/migration.rdoc +1 -1
- data/doc/object_model.rdoc +29 -0
- data/doc/release_notes/3.41.0.txt +155 -0
- data/lib/sequel/adapters/ado.rb +4 -4
- data/lib/sequel/adapters/amalgalite.rb +0 -5
- data/lib/sequel/adapters/cubrid.rb +2 -2
- data/lib/sequel/adapters/db2.rb +9 -5
- data/lib/sequel/adapters/dbi.rb +4 -6
- data/lib/sequel/adapters/do.rb +4 -5
- data/lib/sequel/adapters/firebird.rb +8 -4
- data/lib/sequel/adapters/ibmdb.rb +2 -3
- data/lib/sequel/adapters/informix.rb +0 -6
- data/lib/sequel/adapters/jdbc.rb +11 -7
- data/lib/sequel/adapters/jdbc/db2.rb +22 -0
- data/lib/sequel/adapters/jdbc/derby.rb +5 -5
- data/lib/sequel/adapters/jdbc/h2.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +1 -1
- data/lib/sequel/adapters/jdbc/sqlserver.rb +6 -0
- data/lib/sequel/adapters/mock.rb +3 -3
- data/lib/sequel/adapters/mysql.rb +7 -7
- data/lib/sequel/adapters/mysql2.rb +0 -5
- data/lib/sequel/adapters/odbc.rb +4 -4
- data/lib/sequel/adapters/openbase.rb +4 -6
- data/lib/sequel/adapters/oracle.rb +14 -6
- data/lib/sequel/adapters/postgres.rb +12 -8
- data/lib/sequel/adapters/shared/db2.rb +5 -0
- data/lib/sequel/adapters/shared/firebird.rb +10 -0
- data/lib/sequel/adapters/shared/mssql.rb +43 -1
- data/lib/sequel/adapters/shared/mysql.rb +1 -0
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +12 -0
- data/lib/sequel/adapters/shared/sqlite.rb +32 -0
- data/lib/sequel/adapters/sqlite.rb +9 -8
- data/lib/sequel/adapters/swift.rb +3 -8
- data/lib/sequel/adapters/tinytds.rb +5 -5
- data/lib/sequel/connection_pool.rb +13 -19
- data/lib/sequel/connection_pool/sharded_single.rb +12 -12
- data/lib/sequel/connection_pool/sharded_threaded.rb +37 -17
- data/lib/sequel/connection_pool/single.rb +6 -3
- data/lib/sequel/connection_pool/threaded.rb +33 -13
- data/lib/sequel/database/connecting.rb +28 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +2 -5
- data/lib/sequel/database/query.rb +2 -2
- data/lib/sequel/database/schema_generator.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +3 -0
- data/lib/sequel/dataset/query.rb +8 -4
- data/lib/sequel/dataset/sql.rb +7 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +1 -1
- data/lib/sequel/extensions/connection_validator.rb +109 -0
- data/lib/sequel/extensions/pg_array.rb +2 -0
- data/lib/sequel/extensions/pg_hstore.rb +2 -0
- data/lib/sequel/extensions/pg_json.rb +4 -0
- data/lib/sequel/extensions/pg_range.rb +1 -0
- data/lib/sequel/extensions/pg_row.rb +4 -0
- data/lib/sequel/plugins/prepared_statements.rb +2 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +53 -10
- data/lib/sequel/plugins/touch.rb +18 -6
- data/lib/sequel/plugins/validation_class_methods.rb +1 -0
- data/lib/sequel/plugins/validation_helpers.rb +3 -1
- data/lib/sequel/sql.rb +61 -19
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/firebird_spec.rb +52 -38
- data/spec/adapters/mssql_spec.rb +67 -0
- data/spec/adapters/mysql_spec.rb +192 -116
- data/spec/adapters/postgres_spec.rb +133 -70
- data/spec/adapters/spec_helper.rb +7 -0
- data/spec/adapters/sqlite_spec.rb +34 -1
- data/spec/core/connection_pool_spec.rb +79 -75
- data/spec/core/database_spec.rb +9 -4
- data/spec/core/dataset_spec.rb +15 -0
- data/spec/core/expression_filters_spec.rb +40 -2
- data/spec/extensions/connection_validator_spec.rb +118 -0
- data/spec/extensions/pg_array_spec.rb +4 -0
- data/spec/extensions/single_table_inheritance_spec.rb +42 -0
- data/spec/extensions/touch_spec.rb +40 -0
- data/spec/extensions/validation_class_methods_spec.rb +19 -1
- data/spec/extensions/validation_helpers_spec.rb +17 -0
- data/spec/integration/database_test.rb +14 -0
- data/spec/integration/dataset_test.rb +3 -3
- data/spec/integration/plugin_test.rb +41 -12
- data/spec/integration/schema_test.rb +14 -0
- data/spec/integration/spec_helper.rb +7 -0
- data/spec/integration/type_test.rb +3 -0
- metadata +9 -3
@@ -229,6 +229,14 @@ module Sequel
|
|
229
229
|
conn
|
230
230
|
end
|
231
231
|
|
232
|
+
# Disconnect given connection
|
233
|
+
def disconnect_connection(conn)
|
234
|
+
begin
|
235
|
+
conn.finish
|
236
|
+
rescue PGError
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
232
240
|
# Execute the given SQL with the given args on an available connection.
|
233
241
|
def execute(sql, opts={}, &block)
|
234
242
|
synchronize(opts[:server]){|conn| check_database_errors{_execute(conn, sql, opts, &block)}}
|
@@ -453,14 +461,10 @@ module Sequel
|
|
453
461
|
sqls
|
454
462
|
end
|
455
463
|
|
456
|
-
|
457
|
-
|
458
|
-
begin
|
459
|
-
conn.finish
|
460
|
-
rescue PGError
|
461
|
-
end
|
464
|
+
def database_error_classes
|
465
|
+
[PGError]
|
462
466
|
end
|
463
|
-
|
467
|
+
|
464
468
|
# Execute the prepared statement with the given name on an available
|
465
469
|
# connection, using the given args. If the connection has not prepared
|
466
470
|
# a statement with the given name yet, prepare it. If the connection
|
@@ -479,8 +483,8 @@ module Sequel
|
|
479
483
|
|
480
484
|
unless conn.prepared_statements[ps_name] == sql
|
481
485
|
conn.execute("DEALLOCATE #{ps_name}") if conn.prepared_statements.include?(ps_name)
|
482
|
-
conn.prepared_statements[ps_name] = sql
|
483
486
|
conn.check_disconnect_errors{log_yield("PREPARE #{ps_name} AS #{sql}"){conn.prepare(ps_name, sql)}}
|
487
|
+
conn.prepared_statements[ps_name] = sql
|
484
488
|
end
|
485
489
|
|
486
490
|
log_sql = "EXECUTE #{ps_name}"
|
@@ -176,6 +176,11 @@ module Sequel
|
|
176
176
|
"CALL ADMIN_CMD(#{literal("REORG TABLE #{table}")})"
|
177
177
|
end
|
178
178
|
|
179
|
+
# Treat clob as blob if use_clob_as_blob is true
|
180
|
+
def schema_column_type(db_type)
|
181
|
+
(::Sequel::DB2::use_clob_as_blob && db_type.downcase == 'clob') ? :blob : super
|
182
|
+
end
|
183
|
+
|
179
184
|
# We uses the clob type by default for Files.
|
180
185
|
# Note: if user select to use blob, then insert statement should use
|
181
186
|
# use this for blob value:
|
@@ -154,6 +154,7 @@ module Sequel
|
|
154
154
|
INSERT_CLAUSE_METHODS = Dataset.clause_methods(:insert, %w'insert into columns values returning')
|
155
155
|
FIRST = " FIRST ".freeze
|
156
156
|
SKIP = " SKIP ".freeze
|
157
|
+
DEFAULT_FROM = " FROM RDB$DATABASE"
|
157
158
|
|
158
159
|
# Insert given values into the database.
|
159
160
|
def insert(*values)
|
@@ -206,6 +207,15 @@ module Sequel
|
|
206
207
|
SELECT_CLAUSE_METHODS
|
207
208
|
end
|
208
209
|
|
210
|
+
# Use a default FROM table if the dataset does not contain a FROM table.
|
211
|
+
def select_from_sql(sql)
|
212
|
+
if @opts[:from]
|
213
|
+
super
|
214
|
+
else
|
215
|
+
sql << DEFAULT_FROM
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
209
219
|
def select_limit_sql(sql)
|
210
220
|
if l = @opts[:limit]
|
211
221
|
sql << FIRST
|
@@ -13,6 +13,7 @@ module Sequel
|
|
13
13
|
SQL_ROLLBACK_TO_SAVEPOINT = 'IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION autopoint_%d'.freeze
|
14
14
|
SQL_SAVEPOINT = 'SAVE TRANSACTION autopoint_%d'.freeze
|
15
15
|
MSSQL_DEFAULT_RE = /\A(?:\(N?('.*')\)|\(\((-?\d+(?:\.\d+)?)\)\))\z/
|
16
|
+
FOREIGN_KEY_ACTION_MAP = {0 => :no_action, 1 => :cascade, 2 => :set_null, 3 => :set_default}.freeze
|
16
17
|
|
17
18
|
include Sequel::Database::SplitAlterTable
|
18
19
|
|
@@ -36,6 +37,47 @@ module Sequel
|
|
36
37
|
false
|
37
38
|
end
|
38
39
|
|
40
|
+
# Return foreign key information using the system views, including
|
41
|
+
# :name, :on_delete, and :on_update entries in the hashes.
|
42
|
+
def foreign_key_list(table, opts={})
|
43
|
+
m = output_identifier_meth
|
44
|
+
im = input_identifier_meth
|
45
|
+
schema, table = schema_and_table(table)
|
46
|
+
current_schema = m.call(get(Sequel.function('schema_name')))
|
47
|
+
fk_action_map = FOREIGN_KEY_ACTION_MAP
|
48
|
+
ds = metadata_dataset.from(:sys__foreign_keys___fk).
|
49
|
+
join(:sys__foreign_key_columns___fkc, :constraint_object_id => :object_id).
|
50
|
+
join(:sys__all_columns___pc, :object_id => :fkc__parent_object_id, :column_id => :fkc__parent_column_id).
|
51
|
+
join(:sys__all_columns___rc, :object_id => :fkc__referenced_object_id, :column_id => :fkc__referenced_column_id).
|
52
|
+
where{{object_schema_name(:fk__parent_object_id) => im.call(schema || current_schema)}}.
|
53
|
+
where{{object_name(:fk__parent_object_id) => im.call(table)}}.
|
54
|
+
select{[:fk__name,
|
55
|
+
:fk__delete_referential_action,
|
56
|
+
:fk__update_referential_action,
|
57
|
+
:pc__name___column,
|
58
|
+
:rc__name___referenced_column,
|
59
|
+
object_schema_name(:fk__referenced_object_id).as(:schema),
|
60
|
+
object_name(:fk__referenced_object_id).as(:table)]}.
|
61
|
+
order(:name, :fkc__constraint_column_id)
|
62
|
+
h = {}
|
63
|
+
ds.each do |row|
|
64
|
+
if r = h[row[:name]]
|
65
|
+
r[:columns] << m.call(row[:column])
|
66
|
+
r[:key] << m.call(row[:referenced_column])
|
67
|
+
else
|
68
|
+
referenced_schema = m.call(row[:schema])
|
69
|
+
referenced_table = m.call(row[:table])
|
70
|
+
h[row[:name]] = { :name => m.call(row[:name]),
|
71
|
+
:table => (referenced_schema == current_schema) ? referenced_table : :"#{referenced_schema}__#{referenced_table}",
|
72
|
+
:columns => [m.call(row[:column])],
|
73
|
+
:key => [m.call(row[:referenced_column])],
|
74
|
+
:on_update => fk_action_map[row[:update_referential_action]],
|
75
|
+
:on_delete => fk_action_map[row[:delete_referential_action]] }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
h.values
|
79
|
+
end
|
80
|
+
|
39
81
|
# Use the system tables to get index information
|
40
82
|
def indexes(table, opts={})
|
41
83
|
m = output_identifier_meth
|
@@ -203,7 +245,7 @@ module Sequel
|
|
203
245
|
if server_version >= 9000000
|
204
246
|
table_name = schema_and_table(table).compact.join('.')
|
205
247
|
self[:sys__default_constraints].
|
206
|
-
where{{:parent_object_id => object_id
|
248
|
+
where{{:parent_object_id => Sequel::SQL::Function.new(:object_id, table_name), col_name(:parent_object_id, :parent_column_id) => column_name.to_s}}.
|
207
249
|
get(:name)
|
208
250
|
end
|
209
251
|
end
|
@@ -195,6 +195,7 @@ module Sequel
|
|
195
195
|
opts[:null] = o == :set_column_null ? op[:null] : opts[:allow_null]
|
196
196
|
opts[:default] = o == :set_column_default ? op[:default] : opts[:ruby_default]
|
197
197
|
opts.delete(:default) if opts[:default] == nil
|
198
|
+
opts.delete(:primary_key)
|
198
199
|
"CHANGE COLUMN #{quote_identifier(op[:name])} #{column_definition_sql(op.merge(opts))}"
|
199
200
|
when :drop_constraint
|
200
201
|
type = case op[:type]
|
@@ -56,8 +56,8 @@ module Sequel
|
|
56
56
|
sql = ps.prepared_sql
|
57
57
|
synchronize(opts[:server]) do |conn|
|
58
58
|
unless conn.prepared_statements[ps_name] == sql
|
59
|
-
conn.prepared_statements[ps_name] = sql
|
60
59
|
_execute(conn, "PREPARE #{ps_name} FROM #{literal(sql)}", opts)
|
60
|
+
conn.prepared_statements[ps_name] = sql
|
61
61
|
end
|
62
62
|
i = 0
|
63
63
|
_execute(conn, "SET " + args.map {|arg| "@sequel_arg_#{i+=1} = #{literal(arg)}"}.join(", "), opts) unless args.empty?
|
@@ -97,6 +97,7 @@ module Sequel
|
|
97
97
|
SYSTEM_TABLE_REGEXP = /^pg|sql/.freeze
|
98
98
|
FOREIGN_KEY_LIST_ON_DELETE_MAP = {'a'.freeze=>:no_action, 'r'.freeze=>:restrict, 'c'.freeze=>:cascade, 'n'.freeze=>:set_null, 'd'.freeze=>:set_default}.freeze
|
99
99
|
POSTGRES_DEFAULT_RE = /\A(?:B?('.*')::[^']+|\((-?\d+(?:\.\d+)?)\))\z/
|
100
|
+
UNLOGGED = 'UNLOGGED '.freeze
|
100
101
|
|
101
102
|
# SQL fragment for custom sequences (ones not created by serial primary key),
|
102
103
|
# Returning the schema and literal form of the sequence name, by parsing
|
@@ -634,6 +635,17 @@ module Sequel
|
|
634
635
|
"CREATE SCHEMA #{quote_identifier(name)}"
|
635
636
|
end
|
636
637
|
|
638
|
+
# DDL statement for creating a table with the given name, columns, and options
|
639
|
+
def create_table_prefix_sql(name, options)
|
640
|
+
temp_or_unlogged_sql = if options[:temp]
|
641
|
+
raise(Error, "can't provide both :temp and :unlogged to create_table") if options[:unlogged]
|
642
|
+
temporary_table_sql
|
643
|
+
elsif options[:unlogged]
|
644
|
+
UNLOGGED
|
645
|
+
end
|
646
|
+
"CREATE #{temp_or_unlogged_sql}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{options[:temp] ? quote_identifier(name) : quote_schema_table(name)}"
|
647
|
+
end
|
648
|
+
|
637
649
|
# Use a PostgreSQL-specific create table generator
|
638
650
|
def create_table_generator_class
|
639
651
|
Postgres::CreateTableGenerator
|
@@ -10,6 +10,12 @@ module Sequel
|
|
10
10
|
TABLES_FILTER = "type = 'table' AND NOT name = 'sqlite_sequence'".freeze
|
11
11
|
TEMP_STORE = [:default, :file, :memory].freeze
|
12
12
|
VIEWS_FILTER = "type = 'view'".freeze
|
13
|
+
TRANSACTION_MODE = {
|
14
|
+
:deferred => "BEGIN DEFERRED TRANSACTION".freeze,
|
15
|
+
:immediate => "BEGIN IMMEDIATE TRANSACTION".freeze,
|
16
|
+
:exclusive => "BEGIN EXCLUSIVE TRANSACTION".freeze,
|
17
|
+
nil => Sequel::Database::SQL_BEGIN,
|
18
|
+
}.freeze
|
13
19
|
|
14
20
|
# Whether to use integers for booleans in the database. SQLite recommends
|
15
21
|
# booleans be stored as integers, but historically Sequel has used 't'/'f'.
|
@@ -35,6 +41,19 @@ module Sequel
|
|
35
41
|
pragma_set(:case_sensitive_like, !!value ? 'on' : 'off') if sqlite_version >= 30203
|
36
42
|
end
|
37
43
|
|
44
|
+
# A symbol signifying the value of the default transaction mode
|
45
|
+
def transaction_mode
|
46
|
+
defined?(@transaction_mode) ? @transaction_mode : (@transaction_mode = nil)
|
47
|
+
end
|
48
|
+
|
49
|
+
def transaction_mode=(value)
|
50
|
+
if TRANSACTION_MODE.include?(value)
|
51
|
+
@transaction_mode = value
|
52
|
+
else
|
53
|
+
raise Error, "Invalid value for transaction_mode. Please specify one of :deferred, :immediate, :exclusive, nil"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
38
57
|
# SQLite uses the :sqlite database type.
|
39
58
|
def database_type
|
40
59
|
:sqlite
|
@@ -244,6 +263,13 @@ module Sequel
|
|
244
263
|
end
|
245
264
|
end
|
246
265
|
|
266
|
+
def begin_new_transaction(conn, opts)
|
267
|
+
mode = opts[:mode] || @transaction_mode
|
268
|
+
sql = TRANSACTION_MODE[mode] or raise Error, "transaction :mode must be one of: :deferred, :immediate, :exclusive, nil"
|
269
|
+
log_connection_execute(conn, sql)
|
270
|
+
set_transaction_isolation(conn, opts)
|
271
|
+
end
|
272
|
+
|
247
273
|
# A name to use for the backup table
|
248
274
|
def backup_table_name(table, opts={})
|
249
275
|
table = table.gsub('`', '')
|
@@ -258,6 +284,12 @@ module Sequel
|
|
258
284
|
sql << " DEFAULT (#{literal(column[:default])})" if column.include?(:default)
|
259
285
|
end
|
260
286
|
|
287
|
+
# Add null/not null SQL fragment to column creation SQL.
|
288
|
+
def column_definition_null_sql(sql, column)
|
289
|
+
column = column.merge(:null=>false) if column[:primary_key]
|
290
|
+
super(sql, column)
|
291
|
+
end
|
292
|
+
|
261
293
|
# Array of PRAGMA SQL statements based on the Database options that should be applied to
|
262
294
|
# new connections.
|
263
295
|
def connection_pragmas
|
@@ -117,6 +117,12 @@ module Sequel
|
|
117
117
|
|
118
118
|
db
|
119
119
|
end
|
120
|
+
|
121
|
+
# Disconnect given connections from the database.
|
122
|
+
def disconnect_connection(c)
|
123
|
+
c.prepared_statements.each_value{|v| v.first.close}
|
124
|
+
c.close
|
125
|
+
end
|
120
126
|
|
121
127
|
# Run the given SQL with the given arguments and yield each row.
|
122
128
|
def execute(sql, opts={}, &block)
|
@@ -244,15 +250,10 @@ module Sequel
|
|
244
250
|
end
|
245
251
|
end
|
246
252
|
|
247
|
-
#
|
253
|
+
# SQLite3 raises ArgumentError in addition to SQLite3::Exception in
|
254
|
+
# some cases, such as operations on a closed database.
|
248
255
|
def database_error_classes
|
249
|
-
[SQLite3::Exception]
|
250
|
-
end
|
251
|
-
|
252
|
-
# Disconnect given connections from the database.
|
253
|
-
def disconnect_connection(c)
|
254
|
-
c.prepared_statements.each_value{|v| v.first.close}
|
255
|
-
c.close
|
256
|
+
[SQLite3::Exception, ArgumentError]
|
256
257
|
end
|
257
258
|
end
|
258
259
|
|
@@ -107,15 +107,10 @@ module Sequel
|
|
107
107
|
:execute
|
108
108
|
end
|
109
109
|
|
110
|
-
|
111
|
-
|
110
|
+
def database_error_classes
|
111
|
+
[::Swift::Error]
|
112
112
|
end
|
113
|
-
|
114
|
-
# Execute SQL on the connection
|
115
|
-
def log_connection_execute(conn, sql)
|
116
|
-
log_yield(sql){conn.execute(sql)}
|
117
|
-
end
|
118
|
-
|
113
|
+
|
119
114
|
# Set the :db entry to the same as the :database entry, since
|
120
115
|
# Swift uses :db.
|
121
116
|
def server_opts(o)
|
@@ -108,16 +108,16 @@ module Sequel
|
|
108
108
|
[TinyTds::Error]
|
109
109
|
end
|
110
110
|
|
111
|
-
# Close the TinyTds::Client object.
|
112
|
-
def disconnect_connection(c)
|
113
|
-
c.close
|
114
|
-
end
|
115
|
-
|
116
111
|
# Return true if the :conn argument is present and not active.
|
117
112
|
def disconnect_error?(e, opts)
|
118
113
|
super || (opts[:conn] && !opts[:conn].active?)
|
119
114
|
end
|
120
115
|
|
116
|
+
# Dispose of any possible results of execution.
|
117
|
+
def log_connection_execute(conn, sql)
|
118
|
+
log_yield(sql){conn.execute(sql).each}
|
119
|
+
end
|
120
|
+
|
121
121
|
# Return a 2 element array with the literal value and type to use
|
122
122
|
# in the prepared statement call for the given value and connection.
|
123
123
|
def ps_arg_type(v)
|
@@ -2,15 +2,13 @@
|
|
2
2
|
# on. This class is not instantiated directly, but subclasses should at
|
3
3
|
# the very least implement the following API:
|
4
4
|
#
|
5
|
-
# initialize(
|
6
|
-
#
|
5
|
+
# initialize(Database, Hash) :: Initialize using the passed Sequel::Database
|
6
|
+
# object and options hash.
|
7
7
|
# hold(Symbol, &block) :: Yield a connection object (obtained from calling
|
8
8
|
# the block passed to +initialize+) to the current block. For sharded
|
9
9
|
# connection pools, the Symbol passed is the shard/server to use.
|
10
|
-
# disconnect(Symbol
|
11
|
-
#
|
12
|
-
# <tt>:disconnection_proc</tt> option in the hash passed to initialize. For sharded
|
13
|
-
# connection pools, the Symbol passed is the shard/server to use.
|
10
|
+
# disconnect(Symbol) :: Disconnect the connection object. For sharded
|
11
|
+
# connection pools, the Symbol passed is the shard/server to use.
|
14
12
|
# servers :: An array of shard/server symbols for all shards/servers that this
|
15
13
|
# connection pool recognizes.
|
16
14
|
# size :: an integer representing the total number of connections in the pool,
|
@@ -39,13 +37,13 @@ class Sequel::ConnectionPool
|
|
39
37
|
# option is provided is provided, use that pool class, otherwise
|
40
38
|
# use a new instance of an appropriate pool subclass based on the
|
41
39
|
# <tt>:single_threaded</tt> and <tt>:servers</tt> options.
|
42
|
-
def get_pool(opts = {}
|
40
|
+
def get_pool(db, opts = {})
|
43
41
|
case v = connection_pool_class(opts)
|
44
42
|
when Class
|
45
|
-
v.new(
|
43
|
+
v.new(db, opts)
|
46
44
|
when Symbol
|
47
45
|
Sequel.ts_require("connection_pool/#{v}")
|
48
|
-
connection_pool_class(opts).new(
|
46
|
+
connection_pool_class(opts).new(db, opts) || raise(Sequel::Error, "No connection pool class found")
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -62,10 +60,9 @@ class Sequel::ConnectionPool
|
|
62
60
|
# connection made, and is usually used to set custom per-connection settings.
|
63
61
|
attr_accessor :after_connect
|
64
62
|
|
65
|
-
# The
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
# The Sequel::Database object tied to this connection pool.
|
64
|
+
attr_accessor :db
|
65
|
+
|
69
66
|
# Instantiates a connection pool with the given options. The block is called
|
70
67
|
# with a single symbol (specifying the server/shard to use) every time a new
|
71
68
|
# connection is needed. The following options are respected for all connection
|
@@ -73,11 +70,8 @@ class Sequel::ConnectionPool
|
|
73
70
|
# :after_connect :: The proc called after each new connection is made, with the
|
74
71
|
# connection object, useful for customizations that you want to apply to all
|
75
72
|
# connections.
|
76
|
-
|
77
|
-
|
78
|
-
def initialize(opts={}, &block)
|
79
|
-
raise(Sequel::Error, "No connection proc specified") unless @connection_proc = block
|
80
|
-
@disconnection_proc = opts[:disconnection_proc]
|
73
|
+
def initialize(db, opts={})
|
74
|
+
@db = db
|
81
75
|
@after_connect = opts[:after_connect]
|
82
76
|
end
|
83
77
|
|
@@ -97,7 +91,7 @@ class Sequel::ConnectionPool
|
|
97
91
|
# and checking for connection errors.
|
98
92
|
def make_new(server)
|
99
93
|
begin
|
100
|
-
conn = @
|
94
|
+
conn = @db.connect(server)
|
101
95
|
@after_connect.call(conn) if @after_connect
|
102
96
|
rescue Exception=>exception
|
103
97
|
raise Sequel.convert_exception_class(exception, Sequel::DatabaseConnectionError)
|
@@ -1,18 +1,15 @@
|
|
1
1
|
# A ShardedSingleConnectionPool is a single threaded connection pool that
|
2
2
|
# works with multiple shards/servers.
|
3
3
|
class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
4
|
-
# Initializes the instance with the supplied block as the connection_proc.
|
5
|
-
#
|
6
4
|
# The single threaded pool takes the following options:
|
7
5
|
#
|
8
6
|
# * :servers - A hash of servers to use. Keys should be symbols. If not
|
9
|
-
# present, will use a single :default server.
|
10
|
-
# be passed to the connection_proc.
|
7
|
+
# present, will use a single :default server.
|
11
8
|
# * :servers_hash - The base hash to use for the servers. By default,
|
12
9
|
# Sequel uses Hash.new(:default). You can use a hash with a default proc
|
13
10
|
# that raises an error if you want to catch all cases where a nonexistent
|
14
11
|
# server is used.
|
15
|
-
def initialize(opts={}
|
12
|
+
def initialize(db, opts={})
|
16
13
|
super
|
17
14
|
@conns = {}
|
18
15
|
@servers = opts.fetch(:servers_hash, Hash.new(:default))
|
@@ -41,9 +38,8 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
|
41
38
|
# #hold, the connection is reestablished. Options:
|
42
39
|
# * :server - Should be a symbol specifing the server to disconnect from,
|
43
40
|
# or an array of symbols to specify multiple servers.
|
44
|
-
def disconnect(opts={}
|
45
|
-
|
46
|
-
(opts[:server] ? Array(opts[:server]) : servers).each{|s| disconnect_server(s, &block)}
|
41
|
+
def disconnect(opts={})
|
42
|
+
(opts[:server] ? Array(opts[:server]) : servers).each{|s| disconnect_server(s)}
|
47
43
|
end
|
48
44
|
|
49
45
|
# Yields the connection to the supplied block for the given server.
|
@@ -53,7 +49,7 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
|
53
49
|
server = pick_server(server)
|
54
50
|
yield(@conns[server] ||= make_new(server))
|
55
51
|
rescue Sequel::DatabaseDisconnectError
|
56
|
-
disconnect_server(server
|
52
|
+
disconnect_server(server)
|
57
53
|
raise
|
58
54
|
end
|
59
55
|
end
|
@@ -65,7 +61,7 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
|
65
61
|
def remove_servers(servers)
|
66
62
|
raise(Sequel::Error, "cannot remove default server") if servers.include?(:default)
|
67
63
|
servers.each do |server|
|
68
|
-
disconnect_server(server
|
64
|
+
disconnect_server(server)
|
69
65
|
@servers.delete(server)
|
70
66
|
end
|
71
67
|
end
|
@@ -80,12 +76,16 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
|
80
76
|
@conns.length
|
81
77
|
end
|
82
78
|
|
79
|
+
def pool_type
|
80
|
+
:sharded_single
|
81
|
+
end
|
82
|
+
|
83
83
|
private
|
84
84
|
|
85
85
|
# Disconnect from the given server, if connected.
|
86
|
-
def disconnect_server(server
|
86
|
+
def disconnect_server(server)
|
87
87
|
if conn = @conns.delete(server)
|
88
|
-
|
88
|
+
db.disconnect_connection(conn)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|