sequel 5.33.0 → 5.58.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 +4 -4
- data/CHANGELOG +318 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +40 -9
- data/doc/association_basics.rdoc +77 -13
- data/doc/cheat_sheet.rdoc +13 -5
- data/doc/code_order.rdoc +0 -12
- data/doc/dataset_filtering.rdoc +2 -2
- data/doc/fork_safety.rdoc +84 -0
- data/doc/migration.rdoc +12 -6
- data/doc/model_plugins.rdoc +1 -1
- data/doc/opening_databases.rdoc +15 -3
- data/doc/postgresql.rdoc +9 -1
- data/doc/querying.rdoc +7 -5
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/release_notes/5.36.0.txt +60 -0
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/release_notes/5.38.0.txt +28 -0
- data/doc/release_notes/5.39.0.txt +19 -0
- data/doc/release_notes/5.40.0.txt +40 -0
- data/doc/release_notes/5.41.0.txt +25 -0
- data/doc/release_notes/5.42.0.txt +136 -0
- data/doc/release_notes/5.43.0.txt +98 -0
- data/doc/release_notes/5.44.0.txt +32 -0
- data/doc/release_notes/5.45.0.txt +34 -0
- data/doc/release_notes/5.46.0.txt +87 -0
- data/doc/release_notes/5.47.0.txt +59 -0
- data/doc/release_notes/5.48.0.txt +14 -0
- data/doc/release_notes/5.49.0.txt +59 -0
- data/doc/release_notes/5.50.0.txt +78 -0
- data/doc/release_notes/5.51.0.txt +47 -0
- data/doc/release_notes/5.52.0.txt +87 -0
- data/doc/release_notes/5.53.0.txt +23 -0
- data/doc/release_notes/5.54.0.txt +27 -0
- data/doc/release_notes/5.55.0.txt +21 -0
- data/doc/release_notes/5.56.0.txt +51 -0
- data/doc/release_notes/5.57.0.txt +23 -0
- data/doc/release_notes/5.58.0.txt +31 -0
- data/doc/sql.rdoc +14 -2
- data/doc/testing.rdoc +10 -1
- data/doc/transactions.rdoc +0 -8
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/ado/access.rb +1 -1
- data/lib/sequel/adapters/ado.rb +17 -17
- data/lib/sequel/adapters/amalgalite.rb +3 -5
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc/derby.rb +8 -0
- data/lib/sequel/adapters/jdbc/h2.rb +60 -10
- data/lib/sequel/adapters/jdbc/hsqldb.rb +6 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +4 -4
- data/lib/sequel/adapters/jdbc/postgresql.rb +4 -4
- data/lib/sequel/adapters/jdbc.rb +29 -19
- data/lib/sequel/adapters/mysql.rb +80 -67
- data/lib/sequel/adapters/mysql2.rb +54 -49
- data/lib/sequel/adapters/odbc.rb +8 -6
- data/lib/sequel/adapters/oracle.rb +5 -4
- data/lib/sequel/adapters/postgres.rb +27 -29
- data/lib/sequel/adapters/shared/access.rb +2 -0
- data/lib/sequel/adapters/shared/db2.rb +30 -0
- data/lib/sequel/adapters/shared/mssql.rb +84 -7
- data/lib/sequel/adapters/shared/mysql.rb +33 -2
- data/lib/sequel/adapters/shared/oracle.rb +82 -7
- data/lib/sequel/adapters/shared/postgres.rb +158 -20
- data/lib/sequel/adapters/shared/sqlanywhere.rb +3 -0
- data/lib/sequel/adapters/shared/sqlite.rb +102 -10
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +60 -18
- data/lib/sequel/adapters/tinytds.rb +2 -1
- data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -1
- data/lib/sequel/ast_transformer.rb +6 -0
- data/lib/sequel/connection_pool/sharded_single.rb +9 -8
- data/lib/sequel/connection_pool/sharded_threaded.rb +10 -10
- data/lib/sequel/connection_pool/single.rb +7 -9
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +33 -24
- data/lib/sequel/database/connecting.rb +3 -4
- data/lib/sequel/database/misc.rb +37 -12
- data/lib/sequel/database/query.rb +3 -1
- data/lib/sequel/database/schema_generator.rb +50 -53
- data/lib/sequel/database/schema_methods.rb +45 -23
- data/lib/sequel/database/transactions.rb +9 -6
- data/lib/sequel/dataset/actions.rb +61 -8
- data/lib/sequel/dataset/features.rb +15 -0
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
- data/lib/sequel/dataset/prepared_statements.rb +2 -0
- data/lib/sequel/dataset/query.rb +114 -11
- data/lib/sequel/dataset/sql.rb +172 -46
- data/lib/sequel/deprecated.rb +3 -1
- data/lib/sequel/exceptions.rb +2 -0
- data/lib/sequel/extensions/_pretty_table.rb +1 -2
- data/lib/sequel/extensions/any_not_empty.rb +1 -1
- data/lib/sequel/extensions/async_thread_pool.rb +438 -0
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/columns_introspection.rb +1 -2
- data/lib/sequel/extensions/core_refinements.rb +38 -11
- data/lib/sequel/extensions/date_arithmetic.rb +36 -24
- data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
- data/lib/sequel/extensions/datetime_parse_to_time.rb +5 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/inflector.rb +9 -1
- data/lib/sequel/extensions/is_distinct_from.rb +139 -0
- data/lib/sequel/extensions/migration.rb +13 -2
- data/lib/sequel/extensions/named_timezones.rb +5 -1
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +1 -0
- data/lib/sequel/extensions/pg_array_ops.rb +6 -2
- data/lib/sequel/extensions/pg_enum.rb +3 -1
- data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +55 -3
- data/lib/sequel/extensions/pg_inet.rb +2 -0
- data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
- data/lib/sequel/extensions/pg_interval.rb +35 -8
- data/lib/sequel/extensions/pg_json.rb +3 -5
- data/lib/sequel/extensions/pg_json_ops.rb +119 -4
- data/lib/sequel/extensions/pg_loose_count.rb +3 -1
- data/lib/sequel/extensions/pg_multirange.rb +372 -0
- data/lib/sequel/extensions/pg_range.rb +7 -19
- data/lib/sequel/extensions/pg_range_ops.rb +39 -9
- data/lib/sequel/extensions/pg_row.rb +1 -1
- data/lib/sequel/extensions/pg_row_ops.rb +25 -1
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/run_transaction_hooks.rb +1 -1
- data/lib/sequel/extensions/s.rb +4 -1
- data/lib/sequel/extensions/schema_dumper.rb +16 -5
- data/lib/sequel/extensions/server_block.rb +8 -12
- data/lib/sequel/extensions/sql_comments.rb +110 -3
- data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
- data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
- data/lib/sequel/extensions/string_agg.rb +1 -1
- data/lib/sequel/extensions/string_date_time.rb +19 -23
- data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +9 -3
- data/lib/sequel/model/associations.rb +342 -114
- data/lib/sequel/model/base.rb +45 -24
- data/lib/sequel/model/errors.rb +10 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model/plugins.rb +8 -3
- data/lib/sequel/model.rb +3 -1
- data/lib/sequel/plugins/association_pks.rb +60 -18
- data/lib/sequel/plugins/association_proxies.rb +3 -0
- data/lib/sequel/plugins/async_thread_pool.rb +39 -0
- data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
- data/lib/sequel/plugins/auto_validations.rb +39 -5
- data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +3 -8
- data/lib/sequel/plugins/column_encryption.rb +728 -0
- data/lib/sequel/plugins/composition.rb +8 -2
- data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
- data/lib/sequel/plugins/constraint_validations.rb +2 -1
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/dataset_associations.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +44 -0
- data/lib/sequel/plugins/enum.rb +124 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +2 -0
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/json_serializer.rb +39 -24
- data/lib/sequel/plugins/lazy_attributes.rb +4 -1
- data/lib/sequel/plugins/many_through_many.rb +108 -9
- data/lib/sequel/plugins/nested_attributes.rb +8 -3
- data/lib/sequel/plugins/pg_array_associations.rb +58 -41
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +2 -0
- data/lib/sequel/plugins/prepared_statements.rb +15 -12
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
- data/lib/sequel/plugins/rcte_tree.rb +37 -35
- data/lib/sequel/plugins/serialization.rb +9 -3
- data/lib/sequel/plugins/serialization_modification_detection.rb +2 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +7 -0
- data/lib/sequel/plugins/sql_comments.rb +189 -0
- data/lib/sequel/plugins/static_cache.rb +1 -1
- data/lib/sequel/plugins/string_stripper.rb +1 -1
- data/lib/sequel/plugins/subclasses.rb +28 -11
- data/lib/sequel/plugins/tactical_eager_loading.rb +8 -2
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/tree.rb +9 -4
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -1
- data/lib/sequel/plugins/validation_helpers.rb +18 -11
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/timezones.rb +20 -17
- data/lib/sequel/version.rb +1 -1
- metadata +93 -39
|
@@ -98,6 +98,11 @@ module Sequel
|
|
|
98
98
|
# The conversion procs to use for this database
|
|
99
99
|
attr_reader :conversion_procs
|
|
100
100
|
|
|
101
|
+
def initialize(opts = OPTS)
|
|
102
|
+
super
|
|
103
|
+
@allow_regexp = typecast_value_boolean(opts[:setup_regexp_function])
|
|
104
|
+
end
|
|
105
|
+
|
|
101
106
|
# Connect to the database. Since SQLite is a file based database,
|
|
102
107
|
# available options are limited:
|
|
103
108
|
#
|
|
@@ -119,6 +124,12 @@ module Sequel
|
|
|
119
124
|
end
|
|
120
125
|
|
|
121
126
|
connection_pragmas.each{|s| log_connection_yield(s, db){db.execute_batch(s)}}
|
|
127
|
+
|
|
128
|
+
if typecast_value_boolean(opts[:setup_regexp_function])
|
|
129
|
+
db.create_function("regexp", 2) do |func, regexp_str, string|
|
|
130
|
+
func.result = Regexp.new(regexp_str).match(string) ? 1 : 0
|
|
131
|
+
end
|
|
132
|
+
end
|
|
122
133
|
|
|
123
134
|
class << db
|
|
124
135
|
attr_reader :prepared_statements
|
|
@@ -128,6 +139,12 @@ module Sequel
|
|
|
128
139
|
db
|
|
129
140
|
end
|
|
130
141
|
|
|
142
|
+
# Whether this Database instance is setup to allow regexp matching.
|
|
143
|
+
# True if the :setup_regexp_function option was passed when creating the Database.
|
|
144
|
+
def allow_regexp?
|
|
145
|
+
@allow_regexp
|
|
146
|
+
end
|
|
147
|
+
|
|
131
148
|
# Disconnect given connections from the database.
|
|
132
149
|
def disconnect_connection(c)
|
|
133
150
|
c.prepared_statements.each_value{|v| v.first.close}
|
|
@@ -189,26 +206,24 @@ module Sequel
|
|
|
189
206
|
# Yield an available connection. Rescue
|
|
190
207
|
# any SQLite3::Exceptions and turn them into DatabaseErrors.
|
|
191
208
|
def _execute(type, sql, opts, &block)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
conn.changes
|
|
207
|
-
end
|
|
209
|
+
synchronize(opts[:server]) do |conn|
|
|
210
|
+
return execute_prepared_statement(conn, type, sql, opts, &block) if sql.is_a?(Symbol)
|
|
211
|
+
log_args = opts[:arguments]
|
|
212
|
+
args = {}
|
|
213
|
+
opts.fetch(:arguments, OPTS).each{|k, v| args[k] = prepared_statement_argument(v)}
|
|
214
|
+
case type
|
|
215
|
+
when :select
|
|
216
|
+
log_connection_yield(sql, conn, log_args){conn.query(sql, args, &block)}
|
|
217
|
+
when :insert
|
|
218
|
+
log_connection_yield(sql, conn, log_args){conn.execute(sql, args)}
|
|
219
|
+
conn.last_insert_row_id
|
|
220
|
+
when :update
|
|
221
|
+
log_connection_yield(sql, conn, log_args){conn.execute_batch(sql, args)}
|
|
222
|
+
conn.changes
|
|
208
223
|
end
|
|
209
|
-
rescue SQLite3::Exception => e
|
|
210
|
-
raise_error(e)
|
|
211
224
|
end
|
|
225
|
+
rescue SQLite3::Exception => e
|
|
226
|
+
raise_error(e)
|
|
212
227
|
end
|
|
213
228
|
|
|
214
229
|
# The SQLite adapter does not need the pool to convert exceptions.
|
|
@@ -323,6 +338,28 @@ module Sequel
|
|
|
323
338
|
BindArgumentMethods = prepared_statements_module(:bind, ArgumentMapper)
|
|
324
339
|
PreparedStatementMethods = prepared_statements_module(:prepare, BindArgumentMethods)
|
|
325
340
|
|
|
341
|
+
# Support regexp functions if using :setup_regexp_function Database option.
|
|
342
|
+
def complex_expression_sql_append(sql, op, args)
|
|
343
|
+
case op
|
|
344
|
+
when :~, :'!~', :'~*', :'!~*'
|
|
345
|
+
return super unless supports_regexp?
|
|
346
|
+
|
|
347
|
+
case_insensitive = [:'~*', :'!~*'].include?(op)
|
|
348
|
+
sql << 'NOT ' if [:'!~', :'!~*'].include?(op)
|
|
349
|
+
sql << '('
|
|
350
|
+
sql << 'LOWER(' if case_insensitive
|
|
351
|
+
literal_append(sql, args[0])
|
|
352
|
+
sql << ')' if case_insensitive
|
|
353
|
+
sql << ' REGEXP '
|
|
354
|
+
sql << 'LOWER(' if case_insensitive
|
|
355
|
+
literal_append(sql, args[1])
|
|
356
|
+
sql << ')' if case_insensitive
|
|
357
|
+
sql << ')'
|
|
358
|
+
else
|
|
359
|
+
super
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
326
363
|
def fetch_rows(sql)
|
|
327
364
|
execute(sql) do |result|
|
|
328
365
|
cps = db.conversion_procs
|
|
@@ -346,6 +383,11 @@ module Sequel
|
|
|
346
383
|
end
|
|
347
384
|
end
|
|
348
385
|
end
|
|
386
|
+
|
|
387
|
+
# Support regexp if using :setup_regexp_function Database option.
|
|
388
|
+
def supports_regexp?
|
|
389
|
+
db.allow_regexp?
|
|
390
|
+
end
|
|
349
391
|
|
|
350
392
|
private
|
|
351
393
|
|
|
@@ -16,6 +16,7 @@ module Sequel
|
|
|
16
16
|
c = TinyTds::Client.new(opts)
|
|
17
17
|
c.query_options.merge!(:cache_rows=>false)
|
|
18
18
|
|
|
19
|
+
# SEQUEL6: Default to ansi: true
|
|
19
20
|
if opts[:ansi]
|
|
20
21
|
sql = %w(
|
|
21
22
|
ANSI_NULLS
|
|
@@ -74,7 +75,7 @@ module Sequel
|
|
|
74
75
|
return r.public_send(m) if m
|
|
75
76
|
end
|
|
76
77
|
end
|
|
77
|
-
yield(r) if
|
|
78
|
+
yield(r) if defined?(yield)
|
|
78
79
|
rescue TinyTds::Error => e
|
|
79
80
|
raise_error(e, :disconnect=>!c.active?)
|
|
80
81
|
ensure
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
class Dataset
|
|
5
|
+
module ColumnsLimit1
|
|
6
|
+
COLUMNS_CLONE_OPTIONS = {:distinct => nil, :limit => 1, :offset=>nil, :where=>nil, :having=>nil, :order=>nil, :row_proc=>nil, :graph=>nil, :eager_graph=>nil}.freeze
|
|
7
|
+
|
|
8
|
+
# Use a limit of 1 instead of a limit of 0 when
|
|
9
|
+
# getting the columns.
|
|
10
|
+
def columns!
|
|
11
|
+
ds = clone(COLUMNS_CLONE_OPTIONS)
|
|
12
|
+
ds.each{break}
|
|
13
|
+
|
|
14
|
+
if cols = ds.cache[:_columns]
|
|
15
|
+
self.columns = cols
|
|
16
|
+
else
|
|
17
|
+
[]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -18,6 +18,7 @@ module Sequel
|
|
|
18
18
|
This connection is still waiting for a result, try again once you have the result
|
|
19
19
|
closed MySQL connection
|
|
20
20
|
The MySQL server is running with the --read-only option so it cannot execute this statement
|
|
21
|
+
Connection was killed
|
|
21
22
|
END
|
|
22
23
|
# Error messages for mysql and mysql2 that indicate the current connection should be disconnected
|
|
23
24
|
MYSQL_DATABASE_DISCONNECT_ERRORS = /\A#{Regexp.union(disconnect_errors)}/
|
|
@@ -33,7 +34,7 @@ module Sequel
|
|
|
33
34
|
def execute(sql, opts=OPTS, &block)
|
|
34
35
|
if opts[:sproc]
|
|
35
36
|
call_sproc(sql, opts, &block)
|
|
36
|
-
elsif sql.is_a?(Symbol)
|
|
37
|
+
elsif sql.is_a?(Symbol) || sql.is_a?(Sequel::Dataset::ArgumentMapper)
|
|
37
38
|
execute_prepared_statement(sql, opts, &block)
|
|
38
39
|
else
|
|
39
40
|
synchronize(opts[:server]){|conn| _execute(conn, sql, opts, &block)}
|
|
@@ -80,6 +80,12 @@ module Sequel
|
|
|
80
80
|
SQL::DelayedEvaluation.new(lambda{|ds| v(o.call(ds))})
|
|
81
81
|
when SQL::Wrapper
|
|
82
82
|
SQL::Wrapper.new(v(o.value))
|
|
83
|
+
when SQL::Expression
|
|
84
|
+
if o.respond_to?(:sequel_ast_transform)
|
|
85
|
+
o.sequel_ast_transform(method(:v))
|
|
86
|
+
else
|
|
87
|
+
o
|
|
88
|
+
end
|
|
83
89
|
else
|
|
84
90
|
o
|
|
85
91
|
end
|
|
@@ -41,7 +41,10 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
|
|
41
41
|
# :server :: Should be a symbol specifing the server to disconnect from,
|
|
42
42
|
# or an array of symbols to specify multiple servers.
|
|
43
43
|
def disconnect(opts=OPTS)
|
|
44
|
-
(opts[:server] ? Array(opts[:server]) : servers).each
|
|
44
|
+
(opts[:server] ? Array(opts[:server]) : servers).each do |s|
|
|
45
|
+
raise Sequel::Error, "invalid server: #{s}" unless @servers.has_key?(s)
|
|
46
|
+
disconnect_server(s)
|
|
47
|
+
end
|
|
45
48
|
end
|
|
46
49
|
|
|
47
50
|
def freeze
|
|
@@ -52,13 +55,11 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
|
|
52
55
|
# Yields the connection to the supplied block for the given server.
|
|
53
56
|
# This method simulates the ConnectionPool#hold API.
|
|
54
57
|
def hold(server=:default)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
raise
|
|
61
|
-
end
|
|
58
|
+
server = pick_server(server)
|
|
59
|
+
yield(@conns[server] ||= make_new(server))
|
|
60
|
+
rescue Sequel::DatabaseDisconnectError, *@error_classes => e
|
|
61
|
+
disconnect_server(server) if disconnect_error?(e)
|
|
62
|
+
raise
|
|
62
63
|
end
|
|
63
64
|
|
|
64
65
|
# The ShardedSingleConnectionPool always has a maximum size of 1.
|
|
@@ -95,9 +95,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
|
95
95
|
# or an array of symbols to specify multiple servers.
|
|
96
96
|
def disconnect(opts=OPTS)
|
|
97
97
|
(opts[:server] ? Array(opts[:server]) : sync{@servers.keys}).each do |s|
|
|
98
|
-
|
|
99
|
-
disconnect_connections(conns)
|
|
100
|
-
end
|
|
98
|
+
disconnect_connections(sync{disconnect_server_connections(s)})
|
|
101
99
|
end
|
|
102
100
|
end
|
|
103
101
|
|
|
@@ -203,9 +201,9 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
|
203
201
|
|
|
204
202
|
until conn = assign_connection(thread, server)
|
|
205
203
|
elapsed = Sequel.elapsed_seconds_since(timer)
|
|
204
|
+
# :nocov:
|
|
206
205
|
raise_pool_timeout(elapsed, server) if elapsed > timeout
|
|
207
206
|
|
|
208
|
-
# :nocov:
|
|
209
207
|
# It's difficult to get to this point, it can only happen if there is a race condition
|
|
210
208
|
# where a connection cannot be acquired even after the thread is signalled by the condition variable
|
|
211
209
|
sync do
|
|
@@ -278,13 +276,15 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
|
278
276
|
# Mark any allocated connections to be removed when they are checked back in. The calling
|
|
279
277
|
# code should already have the mutex before calling this.
|
|
280
278
|
def disconnect_server_connections(server)
|
|
281
|
-
|
|
279
|
+
remove_conns = allocated(server)
|
|
280
|
+
dis_conns = available_connections(server)
|
|
281
|
+
raise Sequel::Error, "invalid server: #{server}" unless remove_conns && dis_conns
|
|
282
282
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
283
|
+
@connections_to_remove.concat(remove_conns.values)
|
|
284
|
+
|
|
285
|
+
conns = dis_conns.dup
|
|
286
|
+
dis_conns.clear
|
|
287
|
+
@waiters[server].signal
|
|
288
288
|
conns
|
|
289
289
|
end
|
|
290
290
|
|
|
@@ -11,7 +11,7 @@ class Sequel::SingleConnectionPool < Sequel::ConnectionPool
|
|
|
11
11
|
|
|
12
12
|
# Yield the connection if one has been made.
|
|
13
13
|
def all_connections
|
|
14
|
-
yield @conn.first
|
|
14
|
+
yield @conn.first unless @conn.empty?
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
# Disconnect the connection from the database.
|
|
@@ -24,15 +24,13 @@ class Sequel::SingleConnectionPool < Sequel::ConnectionPool
|
|
|
24
24
|
|
|
25
25
|
# Yield the connection to the block.
|
|
26
26
|
def hold(server=nil)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@conn.replace([c = make_new(:default)])
|
|
30
|
-
end
|
|
31
|
-
yield c
|
|
32
|
-
rescue Sequel::DatabaseDisconnectError, *@error_classes => e
|
|
33
|
-
disconnect if disconnect_error?(e)
|
|
34
|
-
raise
|
|
27
|
+
unless c = @conn.first
|
|
28
|
+
@conn.replace([c = make_new(:default)])
|
|
35
29
|
end
|
|
30
|
+
yield c
|
|
31
|
+
rescue Sequel::DatabaseDisconnectError, *@error_classes => e
|
|
32
|
+
disconnect if disconnect_error?(e)
|
|
33
|
+
raise
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
# The SingleConnectionPool always has a maximum size of 1.
|
|
@@ -152,9 +152,9 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
|
152
152
|
|
|
153
153
|
until conn = assign_connection(thread)
|
|
154
154
|
elapsed = Sequel.elapsed_seconds_since(timer)
|
|
155
|
+
# :nocov:
|
|
155
156
|
raise_pool_timeout(elapsed) if elapsed > timeout
|
|
156
157
|
|
|
157
|
-
# :nocov:
|
|
158
158
|
# It's difficult to get to this point, it can only happen if there is a race condition
|
|
159
159
|
# where a connection cannot be acquired even after the thread is signalled by the condition variable
|
|
160
160
|
sync do
|
data/lib/sequel/core.rb
CHANGED
|
@@ -52,13 +52,12 @@ module Sequel
|
|
|
52
52
|
#
|
|
53
53
|
# Sequel.datetime_class = DateTime
|
|
54
54
|
#
|
|
55
|
-
# Note that +Time+ and +DateTime+ objects
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
# days on +DateTime+).
|
|
55
|
+
# Note that +Time+ and +DateTime+ objects have a different API, and in
|
|
56
|
+
# cases where they implement the same methods, they often implement them
|
|
57
|
+
# differently (e.g. + using seconds on +Time+ and days on +DateTime+).
|
|
59
58
|
attr_accessor :datetime_class
|
|
60
59
|
|
|
61
|
-
# Set whether Sequel is being used in single threaded mode.
|
|
60
|
+
# Set whether Sequel is being used in single threaded mode. By default,
|
|
62
61
|
# Sequel uses a thread-safe connection pool, which isn't as fast as the
|
|
63
62
|
# single threaded connection pool, and also has some additional thread
|
|
64
63
|
# safety checks. If your program will only have one thread,
|
|
@@ -67,7 +66,7 @@ module Sequel
|
|
|
67
66
|
# Sequel.single_threaded = true
|
|
68
67
|
attr_accessor :single_threaded
|
|
69
68
|
|
|
70
|
-
# Alias of original require method, as Sequel.require
|
|
69
|
+
# Alias of original require method, as Sequel.require does a relative
|
|
71
70
|
# require for backwards compatibility.
|
|
72
71
|
alias orig_require require
|
|
73
72
|
private :orig_require
|
|
@@ -177,6 +176,17 @@ module Sequel
|
|
|
177
176
|
JSON.parse(json, :create_additions=>false)
|
|
178
177
|
end
|
|
179
178
|
|
|
179
|
+
# If a mutex is given, synchronize access using it. If nil is given, just
|
|
180
|
+
# yield to the block. This is designed for cases where a mutex may or may
|
|
181
|
+
# not be provided.
|
|
182
|
+
def synchronize_with(mutex)
|
|
183
|
+
if mutex
|
|
184
|
+
mutex.synchronize{yield}
|
|
185
|
+
else
|
|
186
|
+
yield
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
180
190
|
# Convert each item in the array to the correct type, handling multi-dimensional
|
|
181
191
|
# arrays. For each element in the array or subarrays, call the converter,
|
|
182
192
|
# unless the value is nil.
|
|
@@ -268,11 +278,9 @@ module Sequel
|
|
|
268
278
|
#
|
|
269
279
|
# Sequel.string_to_date('2010-09-10') # Date.civil(2010, 09, 10)
|
|
270
280
|
def string_to_date(string)
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
raise convert_exception_class(e, InvalidValue)
|
|
275
|
-
end
|
|
281
|
+
Date.parse(string, Sequel.convert_two_digit_years)
|
|
282
|
+
rescue => e
|
|
283
|
+
raise convert_exception_class(e, InvalidValue)
|
|
276
284
|
end
|
|
277
285
|
|
|
278
286
|
# Converts the given +string+ into a +Time+ or +DateTime+ object, depending on the
|
|
@@ -280,15 +288,13 @@ module Sequel
|
|
|
280
288
|
#
|
|
281
289
|
# Sequel.string_to_datetime('2010-09-10 10:20:30') # Time.local(2010, 09, 10, 10, 20, 30)
|
|
282
290
|
def string_to_datetime(string)
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
datetime_class.parse(string)
|
|
288
|
-
end
|
|
289
|
-
rescue => e
|
|
290
|
-
raise convert_exception_class(e, InvalidValue)
|
|
291
|
+
if datetime_class == DateTime
|
|
292
|
+
DateTime.parse(string, convert_two_digit_years)
|
|
293
|
+
else
|
|
294
|
+
datetime_class.parse(string)
|
|
291
295
|
end
|
|
296
|
+
rescue => e
|
|
297
|
+
raise convert_exception_class(e, InvalidValue)
|
|
292
298
|
end
|
|
293
299
|
|
|
294
300
|
# Converts the given +string+ into a <tt>Sequel::SQLTime</tt> object.
|
|
@@ -296,11 +302,9 @@ module Sequel
|
|
|
296
302
|
# v = Sequel.string_to_time('10:20:30') # Sequel::SQLTime.parse('10:20:30')
|
|
297
303
|
# DB.literal(v) # => '10:20:30'
|
|
298
304
|
def string_to_time(string)
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
raise convert_exception_class(e, InvalidValue)
|
|
303
|
-
end
|
|
305
|
+
SQLTime.parse(string)
|
|
306
|
+
rescue => e
|
|
307
|
+
raise convert_exception_class(e, InvalidValue)
|
|
304
308
|
end
|
|
305
309
|
|
|
306
310
|
# Unless in single threaded mode, protects access to any mutable
|
|
@@ -390,6 +394,11 @@ module Sequel
|
|
|
390
394
|
|
|
391
395
|
private
|
|
392
396
|
|
|
397
|
+
# Return a hash of date information parsed from the given string.
|
|
398
|
+
def _date_parse(string)
|
|
399
|
+
Date._parse(string)
|
|
400
|
+
end
|
|
401
|
+
|
|
393
402
|
# Helper method that the database adapter class methods that are added to Sequel via
|
|
394
403
|
# metaprogramming use to parse arguments.
|
|
395
404
|
def adapter_method(adapter, *args, &block)
|
|
@@ -36,7 +36,7 @@ module Sequel
|
|
|
36
36
|
c = adapter_class(scheme)
|
|
37
37
|
uri_options = c.send(:uri_to_options, uri)
|
|
38
38
|
uri.query.split('&').map{|s| s.split('=')}.each{|k,v| uri_options[k.to_sym] = v if k && !k.empty?} unless uri.query.to_s.strip.empty?
|
|
39
|
-
uri_options.to_a.each{|k,v| uri_options[k] =
|
|
39
|
+
uri_options.to_a.each{|k,v| uri_options[k] = URI::DEFAULT_PARSER.unescape(v) if v.is_a?(String)}
|
|
40
40
|
opts = uri_options.merge(opts).merge!(:orig_opts=>opts.dup, :uri=>conn_string, :adapter=>scheme)
|
|
41
41
|
end
|
|
42
42
|
when Hash
|
|
@@ -55,12 +55,11 @@ module Sequel
|
|
|
55
55
|
|
|
56
56
|
begin
|
|
57
57
|
db = c.new(opts)
|
|
58
|
-
|
|
59
|
-
if block_given?
|
|
58
|
+
if defined?(yield)
|
|
60
59
|
return yield(db)
|
|
61
60
|
end
|
|
62
61
|
ensure
|
|
63
|
-
if
|
|
62
|
+
if defined?(yield)
|
|
64
63
|
db.disconnect if db
|
|
65
64
|
Sequel.synchronize{::Sequel::DATABASES.delete(db)}
|
|
66
65
|
end
|
data/lib/sequel/database/misc.rb
CHANGED
|
@@ -95,6 +95,8 @@ module Sequel
|
|
|
95
95
|
# options hash.
|
|
96
96
|
#
|
|
97
97
|
# Accepts the following options:
|
|
98
|
+
# :before_preconnect :: Callable that runs after extensions from :preconnect_extensions are loaded,
|
|
99
|
+
# but before any connections are created.
|
|
98
100
|
# :cache_schema :: Whether schema should be cached for this Database instance
|
|
99
101
|
# :default_string_column_size :: The default size of string columns, 255 by default.
|
|
100
102
|
# :extensions :: Extensions to load into this Database instance. Can be a symbol, array of symbols,
|
|
@@ -153,19 +155,28 @@ module Sequel
|
|
|
153
155
|
reset_default_dataset
|
|
154
156
|
adapter_initialize
|
|
155
157
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
keep_reference = typecast_value_boolean(@opts[:keep_reference]) != false
|
|
159
|
+
begin
|
|
160
|
+
Sequel.synchronize{::Sequel::DATABASES.push(self)} if keep_reference
|
|
161
|
+
Sequel::Database.run_after_initialize(self)
|
|
160
162
|
|
|
161
|
-
|
|
163
|
+
initialize_load_extensions(:preconnect_extensions)
|
|
162
164
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
if before_preconnect = @opts[:before_preconnect]
|
|
166
|
+
before_preconnect.call(self)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
if typecast_value_boolean(@opts[:preconnect]) && @pool.respond_to?(:preconnect, true)
|
|
170
|
+
concurrent = typecast_value_string(@opts[:preconnect]) == "concurrently"
|
|
171
|
+
@pool.send(:preconnect, concurrent)
|
|
172
|
+
end
|
|
167
173
|
|
|
168
|
-
|
|
174
|
+
initialize_load_extensions(:extensions)
|
|
175
|
+
test_connection if typecast_value_boolean(@opts.fetch(:test, true)) && respond_to?(:connect, true)
|
|
176
|
+
rescue
|
|
177
|
+
Sequel.synchronize{::Sequel::DATABASES.delete(self)} if keep_reference
|
|
178
|
+
raise
|
|
179
|
+
end
|
|
169
180
|
end
|
|
170
181
|
|
|
171
182
|
# Freeze internal data structures for the Database instance.
|
|
@@ -185,7 +196,9 @@ module Sequel
|
|
|
185
196
|
|
|
186
197
|
# Disallow dup/clone for Database instances
|
|
187
198
|
undef_method :dup, :clone, :initialize_copy
|
|
199
|
+
# :nocov:
|
|
188
200
|
if RUBY_VERSION >= '1.9.3'
|
|
201
|
+
# :nocov:
|
|
189
202
|
undef_method :initialize_clone, :initialize_dup
|
|
190
203
|
end
|
|
191
204
|
|
|
@@ -206,8 +219,7 @@ module Sequel
|
|
|
206
219
|
Sequel.extension(*exts)
|
|
207
220
|
exts.each do |ext|
|
|
208
221
|
if pr = Sequel.synchronize{EXTENSIONS[ext]}
|
|
209
|
-
|
|
210
|
-
Sequel.synchronize{@loaded_extensions << ext}
|
|
222
|
+
if Sequel.synchronize{@loaded_extensions.include?(ext) ? false : (@loaded_extensions << ext)}
|
|
211
223
|
pr.call(self)
|
|
212
224
|
end
|
|
213
225
|
else
|
|
@@ -440,6 +452,19 @@ module Sequel
|
|
|
440
452
|
end
|
|
441
453
|
end
|
|
442
454
|
|
|
455
|
+
# Swallow database errors, unless they are connect/disconnect errors.
|
|
456
|
+
def swallow_database_error
|
|
457
|
+
yield
|
|
458
|
+
rescue Sequel::DatabaseDisconnectError, DatabaseConnectionError
|
|
459
|
+
# Always raise disconnect errors
|
|
460
|
+
raise
|
|
461
|
+
rescue Sequel::DatabaseError
|
|
462
|
+
# Don't raise other database errors.
|
|
463
|
+
nil
|
|
464
|
+
# else
|
|
465
|
+
# Don't rescue other exceptions, they will be raised normally.
|
|
466
|
+
end
|
|
467
|
+
|
|
443
468
|
# Typecast the value to an SQL::Blob
|
|
444
469
|
def typecast_value_blob(value)
|
|
445
470
|
value.is_a?(Sequel::SQL::Blob) ? value : Sequel::SQL::Blob.new(value)
|
|
@@ -236,7 +236,7 @@ module Sequel
|
|
|
236
236
|
when :date
|
|
237
237
|
Sequel.string_to_date(default)
|
|
238
238
|
when :datetime
|
|
239
|
-
|
|
239
|
+
Sequel.string_to_datetime(default)
|
|
240
240
|
when :time
|
|
241
241
|
Sequel.string_to_time(default)
|
|
242
242
|
when :decimal
|
|
@@ -344,7 +344,9 @@ module Sequel
|
|
|
344
344
|
|
|
345
345
|
# Post process the schema values.
|
|
346
346
|
def schema_post_process(cols)
|
|
347
|
+
# :nocov:
|
|
347
348
|
if RUBY_VERSION >= '2.5'
|
|
349
|
+
# :nocov:
|
|
348
350
|
cols.each do |_, h|
|
|
349
351
|
db_type = h[:db_type]
|
|
350
352
|
if db_type.is_a?(String)
|