sequel 3.45.0 → 3.46.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.
- checksums.yaml +7 -0
- data/CHANGELOG +34 -0
- data/README.rdoc +6 -0
- data/Rakefile +46 -33
- data/doc/release_notes/3.46.0.txt +122 -0
- data/doc/schema_modification.rdoc +42 -6
- data/doc/security.rdoc +379 -0
- data/doc/transactions.rdoc +1 -1
- data/lib/sequel/adapters/jdbc/as400.rb +1 -0
- data/lib/sequel/adapters/jdbc/h2.rb +11 -0
- data/lib/sequel/adapters/mysql2.rb +3 -9
- data/lib/sequel/adapters/postgres.rb +34 -2
- data/lib/sequel/adapters/shared/cubrid.rb +5 -0
- data/lib/sequel/adapters/shared/mssql.rb +27 -3
- data/lib/sequel/adapters/shared/mysql.rb +25 -4
- data/lib/sequel/adapters/shared/sqlite.rb +12 -1
- data/lib/sequel/connection_pool.rb +3 -3
- data/lib/sequel/connection_pool/sharded_threaded.rb +7 -8
- data/lib/sequel/connection_pool/threaded.rb +7 -8
- data/lib/sequel/core.rb +5 -2
- data/lib/sequel/database.rb +1 -1
- data/lib/sequel/database/connecting.rb +7 -7
- data/lib/sequel/database/features.rb +88 -0
- data/lib/sequel/database/misc.rb +14 -64
- data/lib/sequel/database/query.rb +0 -332
- data/lib/sequel/database/schema_generator.rb +36 -3
- data/lib/sequel/database/schema_methods.rb +48 -12
- data/lib/sequel/database/transactions.rb +344 -0
- data/lib/sequel/dataset/actions.rb +24 -9
- data/lib/sequel/dataset/mutation.rb +20 -0
- data/lib/sequel/dataset/query.rb +0 -17
- data/lib/sequel/dataset/sql.rb +7 -0
- data/lib/sequel/exceptions.rb +10 -6
- data/lib/sequel/extensions/_pretty_table.rb +2 -2
- data/lib/sequel/extensions/looser_typecasting.rb +10 -0
- data/lib/sequel/extensions/migration.rb +5 -2
- data/lib/sequel/model.rb +1 -1
- data/lib/sequel/model/associations.rb +16 -14
- data/lib/sequel/model/base.rb +14 -2
- data/lib/sequel/plugins/composition.rb +3 -3
- data/lib/sequel/plugins/dirty.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +3 -0
- data/lib/sequel/plugins/serialization.rb +7 -17
- data/lib/sequel/plugins/string_stripper.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +1 -1
- data/lib/sequel/sql.rb +3 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +21 -0
- data/spec/adapters/postgres_spec.rb +35 -8
- data/spec/core/database_spec.rb +4 -0
- data/spec/core/dataset_spec.rb +48 -2
- data/spec/core/schema_generator_spec.rb +10 -1
- data/spec/core/schema_spec.rb +69 -0
- data/spec/extensions/composition_spec.rb +21 -2
- data/spec/extensions/dirty_spec.rb +17 -10
- data/spec/extensions/eager_each_spec.rb +4 -1
- data/spec/extensions/looser_typecasting_spec.rb +16 -19
- data/spec/extensions/migration_spec.rb +7 -1
- data/spec/extensions/serialization_spec.rb +22 -0
- data/spec/extensions/single_table_inheritance_spec.rb +3 -2
- data/spec/extensions/validation_helpers_spec.rb +6 -0
- data/spec/integration/dataset_test.rb +5 -0
- data/spec/integration/schema_test.rb +16 -0
- data/spec/model/associations_spec.rb +40 -0
- data/spec/model/base_spec.rb +21 -1
- data/spec/model/record_spec.rb +3 -0
- metadata +14 -10
data/doc/transactions.rdoc
CHANGED
@@ -8,7 +8,7 @@ Sequel uses autocommit mode by default for all of its database adapters, so in g
|
|
8
8
|
* Migrations if the database supports transactional schema
|
9
9
|
* A few model plugins
|
10
10
|
|
11
|
-
Everywhere else, it is up to
|
11
|
+
Everywhere else, it is up to you to use a database transaction if you want to.
|
12
12
|
|
13
13
|
== Basic Transaction Usage
|
14
14
|
|
@@ -85,6 +85,12 @@ module Sequel
|
|
85
85
|
sql = "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} #{type_literal(op)}"
|
86
86
|
column_definition_order.each{|m| send(:"column_definition_#{m}_sql", sql, op)}
|
87
87
|
sql
|
88
|
+
when :drop_constraint
|
89
|
+
if op[:type] == :primary_key
|
90
|
+
"ALTER TABLE #{quote_schema_table(table)} DROP PRIMARY KEY"
|
91
|
+
else
|
92
|
+
super(table, op)
|
93
|
+
end
|
88
94
|
else
|
89
95
|
super(table, op)
|
90
96
|
end
|
@@ -121,6 +127,11 @@ module Sequel
|
|
121
127
|
PRIMARY_KEY_INDEX_RE
|
122
128
|
end
|
123
129
|
|
130
|
+
# H2 does not support named column constraints.
|
131
|
+
def supports_named_column_constraints?
|
132
|
+
false
|
133
|
+
end
|
134
|
+
|
124
135
|
# Use BIGINT IDENTITY for identity columns that use bigint, fixes
|
125
136
|
# the case where primary_key :column, :type=>Bignum is used.
|
126
137
|
def type_literal_generic_bignum(column)
|
@@ -27,17 +27,11 @@ module Sequel
|
|
27
27
|
# a filter for an autoincrement column equals NULL to return the last
|
28
28
|
# inserted row.
|
29
29
|
# * :charset - Same as :encoding (:encoding takes precendence)
|
30
|
-
# * :config_default_group - The default group to read from the in
|
31
|
-
# the MySQL config file.
|
32
|
-
# * :config_local_infile - If provided, sets the Mysql::OPT_LOCAL_INFILE
|
33
|
-
# option on the connection with the given value.
|
34
|
-
# * :connect_timeout - Set the timeout in seconds before a connection
|
35
|
-
# attempt is abandoned.
|
36
30
|
# * :encoding - Set all the related character sets for this
|
37
31
|
# connection (connection, client, database, server, and results).
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
32
|
+
#
|
33
|
+
# The options hash is also passed to mysql2, and can include mysql2
|
34
|
+
# options such as :local_infile.
|
41
35
|
def connect(server)
|
42
36
|
opts = server_opts(server)
|
43
37
|
opts[:host] ||= 'localhost'
|
@@ -164,7 +164,7 @@ module Sequel
|
|
164
164
|
# conversion is done, so an error is raised if you attempt to retrieve an infinite
|
165
165
|
# timestamp. You can set this to :nil to convert to nil, :string to leave
|
166
166
|
# as a string, or :float to convert to an infinite float.
|
167
|
-
|
167
|
+
attr_reader :convert_infinite_timestamps
|
168
168
|
|
169
169
|
# Add the primary_keys and primary_key_sequences instance variables,
|
170
170
|
# so we can get the correct return values for inserted rows.
|
@@ -233,6 +233,22 @@ module Sequel
|
|
233
233
|
conn
|
234
234
|
end
|
235
235
|
|
236
|
+
def convert_infinite_timestamps=(v)
|
237
|
+
@convert_infinite_timestamps = v
|
238
|
+
pr = old_pr = Postgres.use_iso_date_format ? TYPE_TRANSLATOR.method(:date) : Sequel.method(:string_to_date)
|
239
|
+
if v
|
240
|
+
pr = lambda do |v|
|
241
|
+
case v
|
242
|
+
when *INFINITE_TIMESTAMP_STRINGS
|
243
|
+
infinite_timestamp_value(v)
|
244
|
+
else
|
245
|
+
old_pr.call(v)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
conversion_procs[1082] = pr
|
250
|
+
end
|
251
|
+
|
236
252
|
# Disconnect given connection
|
237
253
|
def disconnect_connection(conn)
|
238
254
|
begin
|
@@ -396,7 +412,7 @@ module Sequel
|
|
396
412
|
# If convert_infinite_timestamps is true and the value is infinite, return an appropriate
|
397
413
|
# value based on the convert_infinite_timestamps setting.
|
398
414
|
def to_application_timestamp(value)
|
399
|
-
if
|
415
|
+
if convert_infinite_timestamps
|
400
416
|
case value
|
401
417
|
when *INFINITE_TIMESTAMP_STRINGS
|
402
418
|
infinite_timestamp_value(value)
|
@@ -504,6 +520,22 @@ module Sequel
|
|
504
520
|
conn.execute(sql)
|
505
521
|
end
|
506
522
|
|
523
|
+
# If the value is an infinite value (either an infinite float or a string returned by
|
524
|
+
# by PostgreSQL for an infinite timestamp), return it without converting it if
|
525
|
+
# convert_infinite_timestamps is set.
|
526
|
+
def typecast_value_date(value)
|
527
|
+
if convert_infinite_timestamps
|
528
|
+
case value
|
529
|
+
when *INFINITE_DATETIME_VALUES
|
530
|
+
value
|
531
|
+
else
|
532
|
+
super
|
533
|
+
end
|
534
|
+
else
|
535
|
+
super
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
507
539
|
# If the value is an infinite value (either an infinite float or a string returned by
|
508
540
|
# by PostgreSQL for an infinite timestamp), return it without converting it if
|
509
541
|
# convert_infinite_timestamps is set.
|
@@ -146,6 +146,11 @@ module Sequel
|
|
146
146
|
nil
|
147
147
|
end
|
148
148
|
|
149
|
+
# CUBRID does not support named column constraints.
|
150
|
+
def supports_named_column_constraints?
|
151
|
+
false
|
152
|
+
end
|
153
|
+
|
149
154
|
# CUBRID doesn't support booleans, it recommends using smallint.
|
150
155
|
def type_literal_generic_trueclass(column)
|
151
156
|
:smallint
|
@@ -414,6 +414,7 @@ module Sequel
|
|
414
414
|
APOS_RE = Dataset::APOS_RE
|
415
415
|
DOUBLE_APOS = Dataset::DOUBLE_APOS
|
416
416
|
INTO = Dataset::INTO
|
417
|
+
DOUBLE_BRACKET_CLOSE = ']]'.freeze
|
417
418
|
DATEPART_SECOND_OPEN = "CAST((datepart(".freeze
|
418
419
|
DATEPART_SECOND_MIDDLE = ') + datepart(ns, '.freeze
|
419
420
|
DATEPART_SECOND_CLOSE = ")/1000000000.0) AS double precision)".freeze
|
@@ -434,6 +435,8 @@ module Sequel
|
|
434
435
|
CASE_INSENSITIVE_COLLATION = 'Latin1_General_CI_AS'.freeze
|
435
436
|
DEFAULT_TIMESTAMP_FORMAT = "'%Y-%m-%dT%H:%M:%S%N%z'".freeze
|
436
437
|
FORMAT_DATE = "'%Y%m%d'".freeze
|
438
|
+
CROSS_APPLY = 'CROSS APPLY'.freeze
|
439
|
+
OUTER_APPLY = 'OUTER APPLY'.freeze
|
437
440
|
|
438
441
|
Sequel::Dataset.def_mutation_method(:disable_insert_output, :output, :module=>self)
|
439
442
|
|
@@ -484,6 +487,11 @@ module Sequel
|
|
484
487
|
end
|
485
488
|
end
|
486
489
|
|
490
|
+
# Uses CROSS APPLY to join the given table into the current dataset.
|
491
|
+
def cross_apply(table)
|
492
|
+
join_table(:cross_apply, table)
|
493
|
+
end
|
494
|
+
|
487
495
|
# Disable the use of INSERT OUTPUT
|
488
496
|
def disable_insert_output
|
489
497
|
clone(:disable_insert_output=>true)
|
@@ -545,6 +553,11 @@ module Sequel
|
|
545
553
|
lock_style(:dirty)
|
546
554
|
end
|
547
555
|
|
556
|
+
# Uses OUTER APPLY to join the given table into the current dataset.
|
557
|
+
def outer_apply(table)
|
558
|
+
join_table(:outer_apply, table)
|
559
|
+
end
|
560
|
+
|
548
561
|
# Include an OUTPUT clause in the eventual INSERT, UPDATE, or DELETE query.
|
549
562
|
#
|
550
563
|
# The first argument is the table to output into, and the second argument
|
@@ -570,10 +583,9 @@ module Sequel
|
|
570
583
|
clone({:output => output})
|
571
584
|
end
|
572
585
|
|
573
|
-
# MSSQL uses [] to quote identifiers.
|
574
|
-
# escaping of ], so you cannot use that character in an identifier.
|
586
|
+
# MSSQL uses [] to quote identifiers.
|
575
587
|
def quoted_identifier_append(sql, name)
|
576
|
-
sql << BRACKET_OPEN << name.to_s << BRACKET_CLOSE
|
588
|
+
sql << BRACKET_OPEN << name.to_s.gsub(/\]/, DOUBLE_BRACKET_CLOSE) << BRACKET_CLOSE
|
577
589
|
end
|
578
590
|
|
579
591
|
# The version of the database server.
|
@@ -729,6 +741,18 @@ module Sequel
|
|
729
741
|
end
|
730
742
|
end
|
731
743
|
|
744
|
+
# Handle CROSS APPLY and OUTER APPLY JOIN types
|
745
|
+
def join_type_sql(join_type)
|
746
|
+
case join_type
|
747
|
+
when :cross_apply
|
748
|
+
CROSS_APPLY
|
749
|
+
when :outer_apply
|
750
|
+
OUTER_APPLY
|
751
|
+
else
|
752
|
+
super
|
753
|
+
end
|
754
|
+
end
|
755
|
+
|
732
756
|
# MSSQL uses a literal hexidecimal number for blob strings
|
733
757
|
def literal_blob_append(sql, v)
|
734
758
|
sql << HEX_START << v.unpack(HSTAR).first
|
@@ -199,13 +199,16 @@ module Sequel
|
|
199
199
|
unless op[:type] || opts[:type]
|
200
200
|
raise Error, "cannot determine database type to use for CHANGE COLUMN operation"
|
201
201
|
end
|
202
|
-
|
202
|
+
opts = op.merge(opts)
|
203
|
+
opts.delete(:auto_increment) if op[:auto_increment] == false
|
204
|
+
"CHANGE COLUMN #{quote_identifier(op[:name])} #{column_definition_sql(opts)}"
|
203
205
|
when :drop_constraint
|
204
206
|
type = case op[:type]
|
205
207
|
when :primary_key
|
206
208
|
"DROP PRIMARY KEY"
|
207
209
|
when :foreign_key
|
208
|
-
|
210
|
+
name = op[:name] || foreign_key_name(table, op[:columns])
|
211
|
+
"DROP FOREIGN KEY #{quote_identifier(name)}"
|
209
212
|
when :unique
|
210
213
|
"DROP INDEX #{quote_identifier(op[:name])}"
|
211
214
|
end
|
@@ -224,6 +227,13 @@ module Sequel
|
|
224
227
|
case op[:op]
|
225
228
|
when :drop_index
|
226
229
|
"#{drop_index_sql(table, op)} ON #{quote_schema_table(table)}"
|
230
|
+
when :drop_constraint
|
231
|
+
if op[:type] == :primary_key
|
232
|
+
if (pk = primary_key_from_schema(table)).length == 1
|
233
|
+
return [alter_table_sql(table, {:op=>:rename_column, :name=>pk.first, :new_name=>pk.first, :auto_increment=>false}), super]
|
234
|
+
end
|
235
|
+
end
|
236
|
+
super
|
227
237
|
else
|
228
238
|
super
|
229
239
|
end
|
@@ -242,7 +252,7 @@ module Sequel
|
|
242
252
|
# operations, since in some cases adding a foreign key constraint in
|
243
253
|
# the same query as other operations results in MySQL error 150.
|
244
254
|
def combinable_alter_table_op?(op)
|
245
|
-
super && !(op[:op] == :add_constraint && op[:type] == :foreign_key)
|
255
|
+
super && !(op[:op] == :add_constraint && op[:type] == :foreign_key) && !(op[:op] == :drop_constraint && op[:type] == :primary_key)
|
246
256
|
end
|
247
257
|
|
248
258
|
# The SQL queries to execute on initial connection
|
@@ -317,6 +327,7 @@ module Sequel
|
|
317
327
|
collate = options.fetch(:collate, Sequel::MySQL.default_collate)
|
318
328
|
generator.constraints.sort_by{|c| (c[:type] == :primary_key) ? -1 : 1}
|
319
329
|
|
330
|
+
# Proc for figuring out the primary key for a given table.
|
320
331
|
key_proc = lambda do |t|
|
321
332
|
if t == name
|
322
333
|
if pk = generator.primary_key_name
|
@@ -329,12 +340,17 @@ module Sequel
|
|
329
340
|
end
|
330
341
|
end
|
331
342
|
|
343
|
+
# Manually set the keys, since MySQL requires one, it doesn't use the primary
|
344
|
+
# key if none are specified.
|
332
345
|
generator.constraints.each do |c|
|
333
346
|
if c[:type] == :foreign_key
|
334
347
|
c[:key] ||= key_proc.call(c[:table])
|
335
348
|
end
|
336
349
|
end
|
337
350
|
|
351
|
+
# Split column constraints into table constraints in some cases:
|
352
|
+
# * foreign key - Always
|
353
|
+
# * unique, primary_key - Only if constraint has a name
|
338
354
|
generator.columns.each do |c|
|
339
355
|
if t = c.delete(:table)
|
340
356
|
same_table = t == name
|
@@ -346,7 +362,7 @@ module Sequel
|
|
346
362
|
generator.constraints.unshift(:type=>:unique, :columns=>Array(k))
|
347
363
|
end
|
348
364
|
|
349
|
-
generator.foreign_key([c[:name]], t, c.merge(:name=>
|
365
|
+
generator.foreign_key([c[:name]], t, c.merge(:name=>c[:foreign_key_constraint_name], :type=>:foreign_key, :key=>key))
|
350
366
|
end
|
351
367
|
end
|
352
368
|
|
@@ -448,6 +464,11 @@ module Sequel
|
|
448
464
|
true
|
449
465
|
end
|
450
466
|
|
467
|
+
# MySQL does not support named column constraints.
|
468
|
+
def supports_named_column_constraints?
|
469
|
+
false
|
470
|
+
end
|
471
|
+
|
451
472
|
# Respect the :size option if given to produce
|
452
473
|
# tinyblob, mediumblob, and longblob if :tiny,
|
453
474
|
# :medium, or :long is given.
|
@@ -221,6 +221,7 @@ module Sequel
|
|
221
221
|
ops.each{|op| alter_table_sql_list(table, [op]).flatten.each{|sql| execute_ddl(sql)}}
|
222
222
|
end
|
223
223
|
end
|
224
|
+
ensure
|
224
225
|
self.foreign_keys = true if fks
|
225
226
|
end
|
226
227
|
|
@@ -255,7 +256,11 @@ module Sequel
|
|
255
256
|
when :primary_key
|
256
257
|
duplicate_table(table){|columns| columns.each{|s| s[:primary_key] = nil}}
|
257
258
|
when :foreign_key
|
258
|
-
|
259
|
+
if op[:columns]
|
260
|
+
duplicate_table(table, :skip_foreign_key_columns=>op[:columns])
|
261
|
+
else
|
262
|
+
duplicate_table(table, :no_foreign_keys=>true)
|
263
|
+
end
|
259
264
|
else
|
260
265
|
duplicate_table(table)
|
261
266
|
end
|
@@ -366,6 +371,12 @@ module Sequel
|
|
366
371
|
if ocp = opts[:old_columns_proc]
|
367
372
|
fks.delete_if{|c| ocp.call(c[:columns].dup) != c[:columns]}
|
368
373
|
end
|
374
|
+
|
375
|
+
# Skip any foreign key columns where a constraint for those
|
376
|
+
# foreign keys is being dropped.
|
377
|
+
if sfkc = opts[:skip_foreign_key_columns]
|
378
|
+
fks.delete_if{|c| c[:columns] == sfkc}
|
379
|
+
end
|
369
380
|
|
370
381
|
constraints.concat(fks.each{|h| h[:type] = :foreign_key})
|
371
382
|
end
|
@@ -18,8 +18,8 @@
|
|
18
18
|
#
|
19
19
|
# add_servers(Array of Symbols) :: start recognizing all shards/servers specified
|
20
20
|
# by the array of symbols.
|
21
|
-
#
|
22
|
-
#
|
21
|
+
# remove_servers(Array of Symbols) :: no longer recognize all shards/servers
|
22
|
+
# specified by the array of symbols.
|
23
23
|
class Sequel::ConnectionPool
|
24
24
|
# The default server to use
|
25
25
|
DEFAULT_SERVER = :default
|
@@ -42,7 +42,7 @@ class Sequel::ConnectionPool
|
|
42
42
|
when Class
|
43
43
|
v.new(db, opts)
|
44
44
|
when Symbol
|
45
|
-
Sequel.
|
45
|
+
Sequel.tsk_require("sequel/connection_pool/#{v}")
|
46
46
|
connection_pool_class(opts).new(db, opts) || raise(Sequel::Error, "No connection pool class found")
|
47
47
|
end
|
48
48
|
end
|
@@ -185,13 +185,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
185
185
|
# returns the connection. The calling code should already have the mutex
|
186
186
|
# before calling this.
|
187
187
|
def checkin_connection(server, conn)
|
188
|
-
|
189
|
-
when :queue
|
190
|
-
available_connections(server).unshift(conn)
|
191
|
-
else
|
192
|
-
available_connections(server) << conn
|
193
|
-
end
|
194
|
-
|
188
|
+
available_connections(server) << conn
|
195
189
|
conn
|
196
190
|
end
|
197
191
|
|
@@ -222,7 +216,12 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
222
216
|
# if there is not currently an available connection for the server.
|
223
217
|
# The calling code should already have the mutex before calling this.
|
224
218
|
def next_available(server)
|
225
|
-
|
219
|
+
case @connection_handling
|
220
|
+
when :queue
|
221
|
+
available_connections(server).shift
|
222
|
+
else
|
223
|
+
available_connections(server).pop
|
224
|
+
end
|
226
225
|
end
|
227
226
|
|
228
227
|
# Returns the connection owned by the supplied thread for the given server,
|
@@ -140,13 +140,7 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
140
140
|
# Return a connection to the pool of available connections, returns the connection.
|
141
141
|
# The calling code should already have the mutex before calling this.
|
142
142
|
def checkin_connection(conn)
|
143
|
-
|
144
|
-
when :queue
|
145
|
-
@available_connections.unshift(conn)
|
146
|
-
else
|
147
|
-
@available_connections << conn
|
148
|
-
end
|
149
|
-
|
143
|
+
@available_connections << conn
|
150
144
|
conn
|
151
145
|
end
|
152
146
|
|
@@ -168,7 +162,12 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
168
162
|
# is not currently an available connection. The calling code should already
|
169
163
|
# have the mutex before calling this.
|
170
164
|
def next_available
|
171
|
-
@
|
165
|
+
case @connection_handling
|
166
|
+
when :queue
|
167
|
+
@available_connections.shift
|
168
|
+
else
|
169
|
+
@available_connections.pop
|
170
|
+
end
|
172
171
|
end
|
173
172
|
|
174
173
|
# Returns the connection owned by the supplied thread,
|
data/lib/sequel/core.rb
CHANGED
@@ -20,7 +20,7 @@
|
|
20
20
|
# Sequel currently adds methods to the Array, Hash, String and Symbol classes by
|
21
21
|
# default. You can either require 'sequel/no_core_ext' or set the
|
22
22
|
# +SEQUEL_NO_CORE_EXTENSIONS+ constant or environment variable before requiring
|
23
|
-
# sequel to have
|
23
|
+
# sequel to have Sequel not add methods to those classes.
|
24
24
|
#
|
25
25
|
# For a more expanded introduction, see the {README}[link:files/README_rdoc.html].
|
26
26
|
# For a quicker introduction, see the {cheat sheet}[link:files/doc/cheat_sheet_rdoc.html].
|
@@ -332,7 +332,7 @@ module Sequel
|
|
332
332
|
else
|
333
333
|
# Yield directly to the block. You don't need to synchronize
|
334
334
|
# access on MRI because the GVL makes certain methods atomic.
|
335
|
-
def self.synchronize
|
335
|
+
def self.synchronize
|
336
336
|
yield
|
337
337
|
end
|
338
338
|
end
|
@@ -422,6 +422,9 @@ module Sequel
|
|
422
422
|
|
423
423
|
# Method that adds a database adapter class method to Sequel that calls
|
424
424
|
# Sequel.adapter_method.
|
425
|
+
#
|
426
|
+
# Do not call this method with untrusted input, as that can result in
|
427
|
+
# arbitrary code execution.
|
425
428
|
def self.def_adapter_method(*adapters) # :nodoc:
|
426
429
|
adapters.each do |adapter|
|
427
430
|
instance_eval("def #{adapter}(*args, &block); adapter_method('#{adapter}', *args, &block) end", __FILE__, __LINE__)
|
data/lib/sequel/database.rb
CHANGED
@@ -15,5 +15,5 @@ module Sequel
|
|
15
15
|
class Database
|
16
16
|
end
|
17
17
|
|
18
|
-
require(%w"connecting dataset dataset_defaults logging misc query schema_generator schema_methods", 'database')
|
18
|
+
require(%w"connecting dataset dataset_defaults logging features misc query transactions schema_generator schema_methods", 'database')
|
19
19
|
end
|
@@ -56,10 +56,7 @@ module Sequel
|
|
56
56
|
uri_options = c.send(:uri_to_options, uri)
|
57
57
|
uri.query.split('&').collect{|s| s.split('=')}.each{|k,v| uri_options[k.to_sym] = v if k && !k.empty?} unless uri.query.to_s.strip.empty?
|
58
58
|
uri_options.to_a.each{|k,v| uri_options[k] = URI.unescape(v) if v.is_a?(String)}
|
59
|
-
opts = opts.merge(:orig_opts=>opts.dup)
|
60
|
-
opts[:uri] = conn_string
|
61
|
-
opts = uri_options.merge(opts)
|
62
|
-
opts[:adapter] = scheme
|
59
|
+
opts = uri_options.merge(opts).merge!(:orig_opts=>opts.dup, :uri=>conn_string, :adapter=>scheme)
|
63
60
|
end
|
64
61
|
when Hash
|
65
62
|
opts = conn_string.merge(opts)
|
@@ -77,14 +74,16 @@ module Sequel
|
|
77
74
|
begin
|
78
75
|
db = c.new(opts)
|
79
76
|
db.test_connection if opts[:test] && db.send(:typecast_value_boolean, opts[:test])
|
80
|
-
|
77
|
+
if block_given?
|
78
|
+
return yield(db)
|
79
|
+
end
|
81
80
|
ensure
|
82
81
|
if block_given?
|
83
82
|
db.disconnect if db
|
84
83
|
Sequel.synchronize{::Sequel::DATABASES.delete(db)}
|
85
84
|
end
|
86
85
|
end
|
87
|
-
|
86
|
+
db
|
88
87
|
end
|
89
88
|
|
90
89
|
# Sets the default single_threaded mode for new databases.
|
@@ -107,7 +106,7 @@ module Sequel
|
|
107
106
|
# Sequel.connect('mydb://user:password@dbserver/mydb')
|
108
107
|
def self.set_adapter_scheme(scheme) # :nodoc:
|
109
108
|
@scheme = scheme
|
110
|
-
ADAPTER_MAP[scheme
|
109
|
+
ADAPTER_MAP[scheme] = self
|
111
110
|
end
|
112
111
|
private_class_method :set_adapter_scheme
|
113
112
|
|
@@ -186,6 +185,7 @@ module Sequel
|
|
186
185
|
#
|
187
186
|
# DB.each_server{|db| db.create_table(:users){primary_key :id; String :name}}
|
188
187
|
def each_server(&block)
|
188
|
+
raise(Error, "Database#each_server must be passed a block") unless block
|
189
189
|
servers.each{|s| self.class.connect(server_opts(s), &block)}
|
190
190
|
end
|
191
191
|
|