sequel 3.7.0 → 3.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +50 -0
- data/doc/advanced_associations.rdoc +4 -3
- data/doc/release_notes/3.7.0.txt +2 -2
- data/doc/release_notes/3.8.0.txt +151 -0
- data/lib/sequel/adapters/jdbc.rb +10 -2
- data/lib/sequel/adapters/jdbc/h2.rb +14 -0
- data/lib/sequel/adapters/mysql.rb +36 -26
- data/lib/sequel/adapters/postgres.rb +27 -19
- data/lib/sequel/adapters/shared/mssql.rb +12 -4
- data/lib/sequel/adapters/shared/mysql.rb +16 -0
- data/lib/sequel/connection_pool.rb +178 -57
- data/lib/sequel/database.rb +60 -12
- data/lib/sequel/database/schema_generator.rb +1 -2
- data/lib/sequel/dataset.rb +10 -1
- data/lib/sequel/dataset/actions.rb +4 -8
- data/lib/sequel/dataset/convenience.rb +9 -2
- data/lib/sequel/dataset/query.rb +2 -5
- data/lib/sequel/dataset/sql.rb +0 -1
- data/lib/sequel/exceptions.rb +3 -3
- data/lib/sequel/metaprogramming.rb +4 -18
- data/lib/sequel/model/associations.rb +2 -2
- data/lib/sequel/model/base.rb +15 -18
- data/lib/sequel/model/default_inflections.rb +0 -1
- data/lib/sequel/model/plugins.rb +3 -2
- data/lib/sequel/plugins/boolean_readers.rb +3 -2
- data/lib/sequel/plugins/identity_map.rb +9 -0
- data/lib/sequel/plugins/validation_helpers.rb +8 -1
- data/lib/sequel/sql.rb +21 -11
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +7 -1
- data/spec/adapters/mysql_spec.rb +22 -0
- data/spec/core/connection_pool_spec.rb +211 -3
- data/spec/core/core_sql_spec.rb +7 -0
- data/spec/core/database_spec.rb +159 -7
- data/spec/core/dataset_spec.rb +33 -0
- data/spec/core/spec_helper.rb +1 -0
- data/spec/extensions/boolean_readers_spec.rb +6 -0
- data/spec/extensions/identity_map_spec.rb +29 -1
- data/spec/extensions/inflector_spec.rb +0 -1
- data/spec/extensions/validation_helpers_spec.rb +23 -0
- data/spec/integration/type_test.rb +1 -1
- metadata +131 -129
@@ -8,7 +8,7 @@ module Sequel
|
|
8
8
|
SQL_BEGIN = "BEGIN TRANSACTION".freeze
|
9
9
|
SQL_COMMIT = "COMMIT TRANSACTION".freeze
|
10
10
|
SQL_ROLLBACK = "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION".freeze
|
11
|
-
SQL_ROLLBACK_TO_SAVEPOINT = 'ROLLBACK TRANSACTION autopoint_%d'.freeze
|
11
|
+
SQL_ROLLBACK_TO_SAVEPOINT = 'IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION autopoint_%d'.freeze
|
12
12
|
SQL_SAVEPOINT = 'SAVE TRANSACTION autopoint_%d'.freeze
|
13
13
|
TEMPORARY = "#".freeze
|
14
14
|
|
@@ -183,7 +183,7 @@ module Sequel
|
|
183
183
|
COMMA_SEPARATOR = ', '.freeze
|
184
184
|
DELETE_CLAUSE_METHODS = Dataset.clause_methods(:delete, %w'with from output from2 where')
|
185
185
|
INSERT_CLAUSE_METHODS = Dataset.clause_methods(:insert, %w'with into columns output values')
|
186
|
-
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'with limit distinct columns from table_options join where group order
|
186
|
+
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'with limit distinct columns from table_options join where group having order compounds')
|
187
187
|
UPDATE_CLAUSE_METHODS = Dataset.clause_methods(:update, %w'with table set output from where')
|
188
188
|
WILDCARD = LiteralString.new('*').freeze
|
189
189
|
CONSTANT_MAP = {:CURRENT_DATE=>'CAST(CURRENT_TIMESTAMP AS DATE)'.freeze, :CURRENT_TIME=>'CAST(CURRENT_TIMESTAMP AS TIME)'.freeze}
|
@@ -230,6 +230,7 @@ module Sequel
|
|
230
230
|
|
231
231
|
# Use the OUTPUT clause to get the value of all columns for the newly inserted record.
|
232
232
|
def insert_select(*values)
|
233
|
+
return unless supports_output_clause?
|
233
234
|
naked.clone(default_server_opts(:sql=>output(nil, [:inserted.*]).insert_sql(*values))).single_record unless opts[:disable_insert_output]
|
234
235
|
end
|
235
236
|
|
@@ -256,6 +257,7 @@ module Sequel
|
|
256
257
|
# dataset.output(:output_table, [:deleted__id, :deleted__name])
|
257
258
|
# dataset.output(:output_table, :id => :inserted__id, :name => :inserted__name)
|
258
259
|
def output(into, values)
|
260
|
+
raise(Error, "SQL Server versions 2000 and earlier do not support the OUTPUT clause") unless supports_output_clause?
|
259
261
|
output = {}
|
260
262
|
case values
|
261
263
|
when Hash
|
@@ -332,6 +334,11 @@ module Sequel
|
|
332
334
|
def supports_multiple_column_in?
|
333
335
|
false
|
334
336
|
end
|
337
|
+
|
338
|
+
# Only 2005+ supports the output clause.
|
339
|
+
def supports_output_clause?
|
340
|
+
server_version >= 9000000
|
341
|
+
end
|
335
342
|
|
336
343
|
# MSSQL 2005+ supports window functions
|
337
344
|
def supports_window_functions?
|
@@ -388,9 +395,9 @@ module Sequel
|
|
388
395
|
blob
|
389
396
|
end
|
390
397
|
|
391
|
-
# Use unicode string syntax for all strings
|
398
|
+
# Use unicode string syntax for all strings. Don't double backslashes.
|
392
399
|
def literal_string(v)
|
393
|
-
"N#{
|
400
|
+
"N'#{v.gsub(/'/, "''")}'"
|
394
401
|
end
|
395
402
|
|
396
403
|
# Use 0 for false on MSSQL
|
@@ -425,6 +432,7 @@ module Sequel
|
|
425
432
|
|
426
433
|
# SQL fragment for MSSQL's OUTPUT clause.
|
427
434
|
def output_sql(sql)
|
435
|
+
return unless supports_output_clause?
|
428
436
|
return unless output = @opts[:output]
|
429
437
|
sql << " OUTPUT #{column_list(output[:select_list])}"
|
430
438
|
if into = output[:into]
|
@@ -179,6 +179,22 @@ module Sequel
|
|
179
179
|
end
|
180
180
|
end
|
181
181
|
|
182
|
+
# Respect the :size option if given to produce
|
183
|
+
# tinyblob, mediumblob, and longblob if :tiny,
|
184
|
+
# :medium, or :long is given.
|
185
|
+
def type_literal_generic_file(column)
|
186
|
+
case column[:size]
|
187
|
+
when :tiny # < 2^8 bytes
|
188
|
+
:tinyblob
|
189
|
+
when :medium # < 2^24 bytes
|
190
|
+
:mediumblob
|
191
|
+
when :long # < 2^32 bytes
|
192
|
+
:longblob
|
193
|
+
else # 2^16 bytes
|
194
|
+
:blob
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
182
198
|
# MySQL has both datetime and timestamp classes, most people are going
|
183
199
|
# to want datetime
|
184
200
|
def type_literal_generic_datetime(column)
|
@@ -45,39 +45,75 @@ class Sequel::ConnectionPool
|
|
45
45
|
raise(Sequel::Error, ':max_connections must be positive') if @max_size < 1
|
46
46
|
@mutex = Mutex.new
|
47
47
|
@connection_proc = block
|
48
|
-
@disconnection_proc = opts[:disconnection_proc]
|
49
|
-
@
|
50
|
-
@
|
51
|
-
@
|
52
|
-
@
|
53
|
-
|
54
|
-
|
55
|
-
@allocated[s] = {}
|
56
|
-
end
|
48
|
+
@disconnection_proc = opts[:disconnection_proc]
|
49
|
+
@available_connections = {}
|
50
|
+
@allocated = {}
|
51
|
+
@connections_to_remove = []
|
52
|
+
@servers = Hash.new(:default)
|
53
|
+
add_servers([:default])
|
54
|
+
add_servers(opts[:servers].keys) if opts[:servers]
|
57
55
|
@timeout = Integer(opts[:pool_timeout] || 5)
|
58
56
|
@sleep_time = Float(opts[:pool_sleep_time] || 0.001)
|
59
57
|
@convert_exceptions = opts.include?(:pool_convert_exceptions) ? opts[:pool_convert_exceptions] : true
|
60
58
|
end
|
61
59
|
|
60
|
+
# Adds new servers to the connection pool. Primarily used in conjunction with master/slave
|
61
|
+
# or shard configurations. Allows for dynamic expansion of the potential slaves/shards
|
62
|
+
# at runtime. servers argument should be an array of symbols.
|
63
|
+
def add_servers(servers)
|
64
|
+
sync do
|
65
|
+
servers.each do |server|
|
66
|
+
unless @servers.has_key?(server)
|
67
|
+
@servers[server] = server
|
68
|
+
@available_connections[server] = []
|
69
|
+
@allocated[server] = {}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
62
75
|
# A hash of connections currently being used for the given server, key is the
|
63
|
-
# Thread, value is the connection.
|
76
|
+
# Thread, value is the connection. Nonexistent servers will return nil. Treat
|
77
|
+
# this as read only, do not modify the resulting object.
|
64
78
|
def allocated(server=:default)
|
65
79
|
@allocated[server]
|
66
80
|
end
|
67
81
|
|
68
82
|
# An array of connections opened but not currently used, for the given
|
69
|
-
# server.
|
83
|
+
# server. Nonexistent servers will return nil. Treat this as read only, do
|
84
|
+
# not modify the resulting object.
|
70
85
|
def available_connections(server=:default)
|
71
86
|
@available_connections[server]
|
72
87
|
end
|
73
88
|
|
74
89
|
# The total number of connections opened for the given server, should
|
75
|
-
# be equal to available_connections.length + allocated.length
|
90
|
+
# be equal to available_connections.length + allocated.length. Nonexistent
|
91
|
+
# servers will return the created count of the default server.
|
76
92
|
def created_count(server=:default)
|
93
|
+
server = @servers[server]
|
77
94
|
@allocated[server].length + @available_connections[server].length
|
78
95
|
end
|
79
96
|
alias size created_count
|
80
97
|
|
98
|
+
# Removes all connection currently available on all servers, optionally
|
99
|
+
# yielding each connection to the given block. This method has the effect of
|
100
|
+
# disconnecting from the database, assuming that no connections are currently
|
101
|
+
# being used. If connections are being used, they are scheduled to be
|
102
|
+
# disconnected as soon as they are returned to the pool.
|
103
|
+
#
|
104
|
+
# Once a connection is requested using #hold, the connection pool
|
105
|
+
# creates new connections to the database. Options:
|
106
|
+
# * :server - Should be a symbol specifing the server to disconnect from,
|
107
|
+
# or an array of symbols to specify multiple servers.
|
108
|
+
def disconnect(opts={}, &block)
|
109
|
+
block ||= @disconnection_proc
|
110
|
+
sync do
|
111
|
+
(opts[:server] ? Array(opts[:server]) : @servers.keys).each do |s|
|
112
|
+
disconnect_server(s, &block)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
81
117
|
# Chooses the first available connection to the given server, or if none are
|
82
118
|
# available, creates a new connection. Passes the connection to the supplied
|
83
119
|
# block:
|
@@ -94,27 +130,28 @@ class Sequel::ConnectionPool
|
|
94
130
|
# raised.
|
95
131
|
def hold(server=:default)
|
96
132
|
begin
|
133
|
+
sync{server = @servers[server]}
|
97
134
|
t = Thread.current
|
98
135
|
if conn = owned_connection(t, server)
|
99
136
|
return yield(conn)
|
100
137
|
end
|
101
138
|
begin
|
102
139
|
unless conn = acquire(t, server)
|
103
|
-
time = Time.
|
140
|
+
time = Time.now
|
104
141
|
timeout = time + @timeout
|
105
142
|
sleep_time = @sleep_time
|
106
143
|
sleep sleep_time
|
107
144
|
until conn = acquire(t, server)
|
108
|
-
raise(::Sequel::PoolTimeout) if Time.
|
145
|
+
raise(::Sequel::PoolTimeout) if Time.now > timeout
|
109
146
|
sleep sleep_time
|
110
147
|
end
|
111
148
|
end
|
112
149
|
yield conn
|
113
|
-
rescue Sequel::DatabaseDisconnectError
|
114
|
-
|
150
|
+
rescue Sequel::DatabaseDisconnectError
|
151
|
+
sync{@connections_to_remove << conn} if conn
|
115
152
|
raise
|
116
153
|
ensure
|
117
|
-
|
154
|
+
sync{release(t, conn, server)} if conn
|
118
155
|
end
|
119
156
|
rescue StandardError
|
120
157
|
raise
|
@@ -122,28 +159,37 @@ class Sequel::ConnectionPool
|
|
122
159
|
raise(@convert_exceptions ? RuntimeError.new(e.message) : e)
|
123
160
|
end
|
124
161
|
end
|
125
|
-
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
162
|
+
|
163
|
+
# Remove servers from the connection pool. Primarily used in conjunction with master/slave
|
164
|
+
# or shard configurations. Similar to disconnecting from all given servers,
|
165
|
+
# except that after it is used, future requests for the server will use the
|
166
|
+
# :default server instead.
|
167
|
+
def remove_servers(servers)
|
168
|
+
sync do
|
169
|
+
raise(Sequel::Error, "cannot remove default server") if servers.include?(:default)
|
170
|
+
servers.each do |server|
|
171
|
+
if @servers.include?(server)
|
172
|
+
disconnect_server(server, &@disconnection_proc)
|
173
|
+
@available_connections.delete(server)
|
174
|
+
@allocated.delete(server)
|
175
|
+
@servers.delete(server)
|
176
|
+
end
|
137
177
|
end
|
138
178
|
end
|
139
179
|
end
|
140
|
-
|
180
|
+
|
181
|
+
# Return an array of symbols for servers in the connection pool.
|
182
|
+
def servers
|
183
|
+
sync{@servers.keys}
|
184
|
+
end
|
185
|
+
|
141
186
|
private
|
142
187
|
|
143
188
|
# Assigns a connection to the supplied thread for the given server, if one
|
144
|
-
# is available.
|
189
|
+
# is available. The calling code should NOT already have the mutex when
|
190
|
+
# calling this.
|
145
191
|
def acquire(thread, server)
|
146
|
-
|
192
|
+
sync do
|
147
193
|
if conn = available(server)
|
148
194
|
allocated(server)[thread] = conn
|
149
195
|
end
|
@@ -151,16 +197,30 @@ class Sequel::ConnectionPool
|
|
151
197
|
end
|
152
198
|
|
153
199
|
# Returns an available connection to the given server. If no connection is
|
154
|
-
# available, tries to create a new connection.
|
200
|
+
# available, tries to create a new connection. The calling code should already
|
201
|
+
# have the mutex before calling this.
|
155
202
|
def available(server)
|
156
203
|
available_connections(server).pop || make_new(server)
|
157
204
|
end
|
158
|
-
|
205
|
+
|
206
|
+
# Disconnect from the given server. Disconnects available connections
|
207
|
+
# immediately, and schedules currently allocated connections for disconnection
|
208
|
+
# as soon as they are returned to the pool. The calling code should already
|
209
|
+
# have the mutex before calling this.
|
210
|
+
def disconnect_server(server, &block)
|
211
|
+
if conns = available_connections(server)
|
212
|
+
conns.each{|conn| block.call(conn)} if block
|
213
|
+
conns.clear
|
214
|
+
end
|
215
|
+
@connections_to_remove.concat(allocated(server).values)
|
216
|
+
end
|
217
|
+
|
159
218
|
# Creates a new connection to the given server if the size of the pool for
|
160
|
-
# the server is less than the maximum size of the pool.
|
219
|
+
# the server is less than the maximum size of the pool. The calling code
|
220
|
+
# should already have the mutex before calling this.
|
161
221
|
def make_new(server)
|
162
222
|
if (n = created_count(server)) >= @max_size
|
163
|
-
allocated(server).
|
223
|
+
allocated(server).to_a.each{|t, c| release(t, c, server) unless t.alive?}
|
164
224
|
n = nil
|
165
225
|
end
|
166
226
|
if (n || created_count(server)) < @max_size
|
@@ -176,23 +236,35 @@ class Sequel::ConnectionPool
|
|
176
236
|
end
|
177
237
|
|
178
238
|
# Returns the connection owned by the supplied thread for the given server,
|
179
|
-
# if any.
|
239
|
+
# if any. The calling code should NOT already have the mutex before calling this.
|
180
240
|
def owned_connection(thread, server)
|
181
|
-
|
241
|
+
sync{@allocated[server][thread]}
|
182
242
|
end
|
183
243
|
|
184
|
-
# Releases the connection assigned to the supplied thread and server.
|
185
|
-
#
|
186
|
-
|
187
|
-
|
244
|
+
# Releases the connection assigned to the supplied thread and server. If the
|
245
|
+
# server or connection given is scheduled for disconnection, remove the
|
246
|
+
# connection instead of releasing it back to the pool.
|
247
|
+
# The calling code should already have the mutex before calling this.
|
248
|
+
def release(thread, conn, server)
|
249
|
+
if @connections_to_remove.include?(conn)
|
250
|
+
remove(thread, conn, server)
|
251
|
+
else
|
252
|
+
available_connections(server) << allocated(server).delete(thread)
|
253
|
+
end
|
188
254
|
end
|
189
255
|
|
190
|
-
# Removes the currently allocated connection from the connection pool.
|
256
|
+
# Removes the currently allocated connection from the connection pool. The
|
257
|
+
# calling code should already have the mutex before calling this.
|
191
258
|
def remove(thread, conn, server)
|
192
|
-
@
|
193
|
-
|
194
|
-
|
195
|
-
|
259
|
+
@connections_to_remove.delete(conn)
|
260
|
+
allocated(server).delete(thread) if @servers.include?(server)
|
261
|
+
@disconnection_proc.call(conn) if @disconnection_proc
|
262
|
+
end
|
263
|
+
|
264
|
+
# Yield to the block while inside the mutex. The calling code should NOT
|
265
|
+
# already have the mutex before calling this.
|
266
|
+
def sync
|
267
|
+
@mutex.synchronize{yield}
|
196
268
|
end
|
197
269
|
end
|
198
270
|
|
@@ -220,12 +292,31 @@ class Sequel::SingleThreadedPool
|
|
220
292
|
@connection_proc = block
|
221
293
|
@disconnection_proc = opts[:disconnection_proc]
|
222
294
|
@conns = {}
|
295
|
+
@servers = Hash.new(:default)
|
296
|
+
add_servers([:default])
|
297
|
+
add_servers(opts[:servers].keys) if opts[:servers]
|
223
298
|
@convert_exceptions = opts.include?(:pool_convert_exceptions) ? opts[:pool_convert_exceptions] : true
|
224
299
|
end
|
225
300
|
|
301
|
+
# Adds new servers to the connection pool. Primarily used in conjunction with master/slave
|
302
|
+
# or shard configurations. Allows for dynamic expansion of the potential slaves/shards
|
303
|
+
# at runtime. servers argument should be an array of symbols.
|
304
|
+
def add_servers(servers)
|
305
|
+
servers.each{|s| @servers[s] = s}
|
306
|
+
end
|
307
|
+
|
226
308
|
# The connection for the given server.
|
227
309
|
def conn(server=:default)
|
228
|
-
@conns[server]
|
310
|
+
@conns[@servers[server]]
|
311
|
+
end
|
312
|
+
|
313
|
+
# Disconnects from the database. Once a connection is requested using
|
314
|
+
# #hold, the connection is reestablished. Options:
|
315
|
+
# * :server - Should be a symbol specifing the server to disconnect from,
|
316
|
+
# or an array of symbols to specify multiple servers.
|
317
|
+
def disconnect(opts={}, &block)
|
318
|
+
block ||= @disconnection_proc
|
319
|
+
(opts[:server] ? Array(opts[:server]) : servers).each{|s| disconnect_server(s, &block)}
|
229
320
|
end
|
230
321
|
|
231
322
|
# Yields the connection to the supplied block for the given server.
|
@@ -233,10 +324,10 @@ class Sequel::SingleThreadedPool
|
|
233
324
|
def hold(server=:default)
|
234
325
|
begin
|
235
326
|
begin
|
236
|
-
|
327
|
+
server = @servers[server]
|
328
|
+
yield(c = (@conns[server] ||= make_new(server)))
|
237
329
|
rescue Sequel::DatabaseDisconnectError
|
238
|
-
|
239
|
-
@disconnection_proc.call(c) if @disconnection_proc
|
330
|
+
disconnect_server(server, &@disconnection_proc)
|
240
331
|
raise
|
241
332
|
end
|
242
333
|
rescue Exception => e
|
@@ -245,11 +336,41 @@ class Sequel::SingleThreadedPool
|
|
245
336
|
end
|
246
337
|
end
|
247
338
|
|
248
|
-
#
|
249
|
-
#
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
339
|
+
# Remove servers from the connection pool. Primarily used in conjunction with master/slave
|
340
|
+
# or shard configurations. Similar to disconnecting from all given servers,
|
341
|
+
# except that after it is used, future requests for the server will use the
|
342
|
+
# :default server instead.
|
343
|
+
def remove_servers(servers)
|
344
|
+
raise(Sequel::Error, "cannot remove default server") if servers.include?(:default)
|
345
|
+
servers.each do |server|
|
346
|
+
disconnect_server(server, &@disconnection_proc)
|
347
|
+
@servers.delete(server)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
# Return an array of symbols for servers in the connection pool.
|
352
|
+
def servers
|
353
|
+
@servers.keys
|
354
|
+
end
|
355
|
+
|
356
|
+
private
|
357
|
+
|
358
|
+
# Disconnect from the given server, if connected.
|
359
|
+
def disconnect_server(server, &block)
|
360
|
+
if conn = @conns.delete(server)
|
361
|
+
block.call(conn) if block
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
# Return a connection to the given server, raising DatabaseConnectionError
|
366
|
+
# if the connection_proc raises an error or doesn't return a valid connection.
|
367
|
+
def make_new(server)
|
368
|
+
begin
|
369
|
+
conn = @connection_proc.call(server)
|
370
|
+
rescue Exception=>exception
|
371
|
+
raise Sequel.convert_exception_class(exception, Sequel::DatabaseConnectionError)
|
372
|
+
end
|
373
|
+
raise(Sequel::DatabaseConnectionError, "Connection parameters not valid") unless conn
|
374
|
+
conn
|
254
375
|
end
|
255
376
|
end
|
data/lib/sequel/database.rb
CHANGED
@@ -255,6 +255,20 @@ module Sequel
|
|
255
255
|
(String === args.first) ? fetch(*args) : from(*args)
|
256
256
|
end
|
257
257
|
|
258
|
+
# Dynamically add new servers or modify server options at runtime. Also adds new
|
259
|
+
# servers to the connection pool. Intended for use with master/slave or shard
|
260
|
+
# configurations where it is useful to add new server hosts at runtime.
|
261
|
+
#
|
262
|
+
# servers argument should be a hash with server name symbol keys and hash or
|
263
|
+
# proc values. If a servers key is already in use, it's value is overridden
|
264
|
+
# with the value provided.
|
265
|
+
#
|
266
|
+
# DB.add_servers(:f=>{:host=>"hash_host_f"})
|
267
|
+
def add_servers(servers)
|
268
|
+
@opts[:servers] = @opts[:servers] ? @opts[:servers].merge(servers) : servers
|
269
|
+
@pool.add_servers(servers.keys)
|
270
|
+
end
|
271
|
+
|
258
272
|
# Call the prepared statement with the given name with the given hash
|
259
273
|
# of arguments.
|
260
274
|
def call(ps_name, hash={})
|
@@ -288,9 +302,20 @@ module Sequel
|
|
288
302
|
end
|
289
303
|
|
290
304
|
# Disconnects all available connections from the connection pool. Any
|
291
|
-
# connections currently in use will not be disconnected.
|
292
|
-
|
293
|
-
|
305
|
+
# connections currently in use will not be disconnected. Options:
|
306
|
+
# * :servers - Should be a symbol specifing the server to disconnect from,
|
307
|
+
# or an array of symbols to specify multiple servers.
|
308
|
+
def disconnect(opts = {})
|
309
|
+
pool.disconnect(opts)
|
310
|
+
end
|
311
|
+
|
312
|
+
# Yield a new database object for every server in the connection pool.
|
313
|
+
# Intended for use in sharded environments where there is a need to make schema
|
314
|
+
# modifications (DDL queries) on each shard.
|
315
|
+
#
|
316
|
+
# DB.each_server{|db| db.create_table(:users){primary_key :id; String :name}}
|
317
|
+
def each_server(&block)
|
318
|
+
servers.each{|s| self.class.connect(server_opts(s), &block)}
|
294
319
|
end
|
295
320
|
|
296
321
|
# Executes the given SQL on the database. This method should be overridden in descendants.
|
@@ -431,6 +456,26 @@ module Sequel
|
|
431
456
|
@quote_identifiers = @opts.include?(:quote_identifiers) ? @opts[:quote_identifiers] : (@@quote_identifiers.nil? ? quote_identifiers_default : @@quote_identifiers)
|
432
457
|
end
|
433
458
|
|
459
|
+
# Dynamically remove existing servers from the connection pool. Intended for
|
460
|
+
# use with master/slave or shard configurations where it is useful to remove
|
461
|
+
# existing server hosts at runtime.
|
462
|
+
#
|
463
|
+
# servers should be symbols or arrays of symbols. If a nonexistent server
|
464
|
+
# is specified, it is ignored. If no servers have been specified for
|
465
|
+
# this database, no changes are made. If you attempt to remove the :default server,
|
466
|
+
# an error will be raised.
|
467
|
+
#
|
468
|
+
# DB.remove_servers(:f1, :f2)
|
469
|
+
def remove_servers(*servers)
|
470
|
+
if @opts[:servers] && !@opts[:servers].empty?
|
471
|
+
servs = @opts[:servers].dup
|
472
|
+
servers.flatten!
|
473
|
+
servers.each{|s| servs.delete(s)}
|
474
|
+
@opts[:servers] = servs
|
475
|
+
@pool.remove_servers(servers)
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
434
479
|
# Runs the supplied SQL statement string on the database server. Returns nil.
|
435
480
|
# Options:
|
436
481
|
# * :server - The server to run the SQL on.
|
@@ -439,11 +484,6 @@ module Sequel
|
|
439
484
|
nil
|
440
485
|
end
|
441
486
|
|
442
|
-
# Returns a new dataset with the select method invoked.
|
443
|
-
def select(*args, &block)
|
444
|
-
dataset.select(*args, &block)
|
445
|
-
end
|
446
|
-
|
447
487
|
# Parse the schema from the database.
|
448
488
|
# Returns the schema for the given table as an array with all members being arrays of length 2,
|
449
489
|
# the first member being the column name, and the second member being a hash of column information.
|
@@ -472,6 +512,16 @@ module Sequel
|
|
472
512
|
@schemas[quoted_name] = cols
|
473
513
|
end
|
474
514
|
|
515
|
+
# Returns a new dataset with the select method invoked.
|
516
|
+
def select(*args, &block)
|
517
|
+
dataset.select(*args, &block)
|
518
|
+
end
|
519
|
+
|
520
|
+
# An array of servers/shards for this Database object.
|
521
|
+
def servers
|
522
|
+
pool.servers
|
523
|
+
end
|
524
|
+
|
475
525
|
# Returns true if the database is using a single-threaded connection pool.
|
476
526
|
def single_threaded?
|
477
527
|
@single_threaded
|
@@ -488,8 +538,7 @@ module Sequel
|
|
488
538
|
end
|
489
539
|
|
490
540
|
# Returns true if a table with the given name exists. This requires a query
|
491
|
-
# to the database
|
492
|
-
# the given table name.
|
541
|
+
# to the database.
|
493
542
|
def table_exists?(name)
|
494
543
|
begin
|
495
544
|
from(name).first
|
@@ -905,7 +954,7 @@ module Sequel
|
|
905
954
|
opts.delete(:servers)
|
906
955
|
opts
|
907
956
|
end
|
908
|
-
|
957
|
+
|
909
958
|
# Raise a database error unless the exception is an Rollback.
|
910
959
|
def transaction_error(e)
|
911
960
|
raise_error(e, :classes=>database_error_classes) unless e.is_a?(Rollback)
|
@@ -996,4 +1045,3 @@ module Sequel
|
|
996
1045
|
end
|
997
1046
|
end
|
998
1047
|
end
|
999
|
-
|