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