sequel 3.7.0 → 3.8.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 +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
|
-
|