sequel 5.100.0 → 5.102.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/lib/sequel/connection_pool/sharded_timed_queue.rb +23 -4
- data/lib/sequel/connection_pool/timed_queue.rb +16 -3
- data/lib/sequel/connection_pool.rb +6 -0
- data/lib/sequel/dataset/actions.rb +9 -0
- data/lib/sequel/extensions/connection_checkout_event_callback.rb +151 -0
- data/lib/sequel/extensions/connection_expiration.rb +1 -1
- data/lib/sequel/extensions/connection_validator.rb +1 -1
- data/lib/sequel/plugins/detect_unnecessary_association_options.rb +164 -0
- data/lib/sequel/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 92eed5c337b361dfde5b948323fb6a0a22ad89ecb2473c284d9e5b70a5eed8e2
|
|
4
|
+
data.tar.gz: dd07fefb9f3d2821479be092a12b87c6e7b92f5d8d8c314ff656741d31e75531
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ea53c48308a031896491a59e57ca3902a9a3478b8d09d12de6548a927991419054fa8698463c18c18cef9801a9c4629dc299b27df03245272bb2296f79ccdc1c
|
|
7
|
+
data.tar.gz: adfd92660e225f0d67948dfdc4aa57c2c61c1118265908f8b6a26fe23179573aff4195aec759575abea984e46fa5d1b62701b75caa8ce7e78838f6434e208527
|
|
@@ -71,7 +71,7 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
71
71
|
while true
|
|
72
72
|
conn = nil
|
|
73
73
|
begin
|
|
74
|
-
break unless (conn = queue
|
|
74
|
+
break unless (conn = available(queue, server)) && !conns[conn]
|
|
75
75
|
conns[conn] = true
|
|
76
76
|
yield conn
|
|
77
77
|
ensure
|
|
@@ -95,7 +95,7 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
95
95
|
def disconnect(opts=OPTS)
|
|
96
96
|
(opts[:server] ? Array(opts[:server]) : sync{@servers.keys}).each do |server|
|
|
97
97
|
raise Sequel::Error, "invalid server" unless queue = sync{@queues[server]}
|
|
98
|
-
while conn = queue
|
|
98
|
+
while conn = available(queue, server)
|
|
99
99
|
disconnect_pool_connection(conn, server)
|
|
100
100
|
end
|
|
101
101
|
fill_queue(server)
|
|
@@ -167,7 +167,7 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
167
167
|
|
|
168
168
|
queue = @queues[server]
|
|
169
169
|
|
|
170
|
-
while conn = queue
|
|
170
|
+
while conn = available(queue, server)
|
|
171
171
|
@sizes[server] -= 1
|
|
172
172
|
conns << conn
|
|
173
173
|
end
|
|
@@ -225,6 +225,12 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
225
225
|
conns.each{|conn| disconnect_connection(conn)}
|
|
226
226
|
end
|
|
227
227
|
|
|
228
|
+
# Only for use by extension that need to disconnect a connection inside acquire.
|
|
229
|
+
# Takes the connection and any arguments accepted by acquire.
|
|
230
|
+
def disconnect_acquired_connection(conn, _, server)
|
|
231
|
+
disconnect_pool_connection(conn, server)
|
|
232
|
+
end
|
|
233
|
+
|
|
228
234
|
# Decrement the current size of the pool for the server when disconnecting connections.
|
|
229
235
|
#
|
|
230
236
|
# Calling code should not have the mutex when calling this.
|
|
@@ -311,7 +317,7 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
311
317
|
# Calling code should not have the mutex when calling this.
|
|
312
318
|
def acquire(thread, server)
|
|
313
319
|
queue = sync{@queues[server]}
|
|
314
|
-
if conn = queue
|
|
320
|
+
if conn = available(queue, server) || try_make_new(server) || wait_until_available(queue, server)
|
|
315
321
|
sync{@allocated[server][thread] = conn}
|
|
316
322
|
else
|
|
317
323
|
name = db.opts[:name]
|
|
@@ -319,6 +325,19 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
319
325
|
end
|
|
320
326
|
end
|
|
321
327
|
|
|
328
|
+
# Return the next connection in the pool if there is one available. Returns nil
|
|
329
|
+
# if no connection is currently available.
|
|
330
|
+
def available(queue, _server)
|
|
331
|
+
queue.pop(timeout: 0)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# Return the next connection in the pool if there is one available. If not, wait
|
|
335
|
+
# until the timeout for a connection to become available. If there is still no
|
|
336
|
+
# available connection, return nil.
|
|
337
|
+
def wait_until_available(queue, _server)
|
|
338
|
+
queue.pop(timeout: @timeout)
|
|
339
|
+
end
|
|
340
|
+
|
|
322
341
|
# Returns the connection owned by the supplied thread for the given server,
|
|
323
342
|
# if any. The calling code should NOT already have the mutex before calling this.
|
|
324
343
|
def owned_connection(thread, server)
|
|
@@ -42,7 +42,7 @@ class Sequel::TimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
42
42
|
while true
|
|
43
43
|
conn = nil
|
|
44
44
|
begin
|
|
45
|
-
break unless (conn =
|
|
45
|
+
break unless (conn = available) && !conns[conn]
|
|
46
46
|
conns[conn] = true
|
|
47
47
|
yield conn
|
|
48
48
|
ensure
|
|
@@ -59,7 +59,7 @@ class Sequel::TimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
59
59
|
# Once a connection is requested using #hold, the connection pool
|
|
60
60
|
# creates new connections to the database.
|
|
61
61
|
def disconnect(opts=OPTS)
|
|
62
|
-
while conn =
|
|
62
|
+
while conn = available
|
|
63
63
|
disconnect_connection(conn)
|
|
64
64
|
end
|
|
65
65
|
fill_queue
|
|
@@ -220,7 +220,7 @@ class Sequel::TimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
220
220
|
#
|
|
221
221
|
# Calling code should not have the mutex when calling this.
|
|
222
222
|
def acquire(thread)
|
|
223
|
-
if conn =
|
|
223
|
+
if conn = available || try_make_new || wait_until_available
|
|
224
224
|
sync{@allocated[thread] = conn}
|
|
225
225
|
else
|
|
226
226
|
name = db.opts[:name]
|
|
@@ -228,6 +228,19 @@ class Sequel::TimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
228
228
|
end
|
|
229
229
|
end
|
|
230
230
|
|
|
231
|
+
# Return the next connection in the pool if there is one available. Returns nil
|
|
232
|
+
# if no connection is currently available.
|
|
233
|
+
def available
|
|
234
|
+
@queue.pop(timeout: 0)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Return the next connection in the pool if there is one available. If not, wait
|
|
238
|
+
# until the timeout for a connection to become available. If there is still no
|
|
239
|
+
# available connection, return nil.
|
|
240
|
+
def wait_until_available
|
|
241
|
+
@queue.pop(timeout: @timeout)
|
|
242
|
+
end
|
|
243
|
+
|
|
231
244
|
# Returns the connection owned by the supplied thread,
|
|
232
245
|
# if any. The calling code should NOT already have the mutex before calling this.
|
|
233
246
|
def owned_connection(thread)
|
|
@@ -131,6 +131,12 @@ class Sequel::ConnectionPool
|
|
|
131
131
|
db.disconnect_connection(conn)
|
|
132
132
|
end
|
|
133
133
|
|
|
134
|
+
# Only for use by extension that need to disconnect a connection inside acquire.
|
|
135
|
+
# Takes the connection and any arguments accepted by acquire.
|
|
136
|
+
def disconnect_acquired_connection(conn, *)
|
|
137
|
+
disconnect_connection(conn)
|
|
138
|
+
end
|
|
139
|
+
|
|
134
140
|
# Whether the given exception is a disconnect exception.
|
|
135
141
|
def disconnect_error?(exception)
|
|
136
142
|
exception.is_a?(Sequel::DatabaseDisconnectError) || db.send(:disconnect_error?, exception, OPTS)
|
|
@@ -372,6 +372,15 @@ module Sequel
|
|
|
372
372
|
# DB[:table].import([:x, :y], DB[:table2].select(:a, :b))
|
|
373
373
|
# # INSERT INTO table (x, y) SELECT a, b FROM table2
|
|
374
374
|
#
|
|
375
|
+
# The return value of this method is undefined and should not be used,
|
|
376
|
+
# except in two cases:
|
|
377
|
+
#
|
|
378
|
+
# * When the <tt>return: :primary_key</tt> option is used.
|
|
379
|
+
# * On PostgreSQL, when the dataset uses RETURNING. In this case, if
|
|
380
|
+
# a single value is returned per row, the return value is an array
|
|
381
|
+
# of those values. If multiple values are returned per row, the
|
|
382
|
+
# return value is an array of hashes.
|
|
383
|
+
#
|
|
375
384
|
# Options:
|
|
376
385
|
# :commit_every :: Open a new transaction for every given number of
|
|
377
386
|
# records. For example, if you provide a value of 50,
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
#
|
|
3
|
+
# The connection_checkout_event_callback extension modifies a database's
|
|
4
|
+
# connection pool to allow for a checkout event callback. This callback is
|
|
5
|
+
# called with the following arguments:
|
|
6
|
+
#
|
|
7
|
+
# :immediately_available :: Connection immediately available and returned
|
|
8
|
+
# :not_immediately_available :: Connection not immediately available
|
|
9
|
+
# :new_connection :: New connection created and returned
|
|
10
|
+
# Float :: Number of seconds waiting to acquire a connection
|
|
11
|
+
#
|
|
12
|
+
# This is a low-level extension that allows for building telemetry
|
|
13
|
+
# information. It doesn't implement any telemetry reporting itself. The
|
|
14
|
+
# main reason for recording this information is to use it to determine the
|
|
15
|
+
# appropriate size for the connection pool. Having too large a connection
|
|
16
|
+
# pool can waste resources, while having too small a connection pool can
|
|
17
|
+
# result in substantial time to check out a connection. In general, you
|
|
18
|
+
# want to use as small a pool as possible while keeping the time to
|
|
19
|
+
# checkout a connection low.
|
|
20
|
+
#
|
|
21
|
+
# To use the connection checkout event callback, you must first load the
|
|
22
|
+
# extension:
|
|
23
|
+
#
|
|
24
|
+
# DB.extension(:connection_checkout_event_callback)
|
|
25
|
+
#
|
|
26
|
+
# By default, an empty proc is used as the callback so that loading the
|
|
27
|
+
# support doesn't break anything. If you are using the extension, you
|
|
28
|
+
# should set the callback at some point during application startup:
|
|
29
|
+
#
|
|
30
|
+
# DB.pool.on_checkout_event = proc do |event|
|
|
31
|
+
# # ...
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# When using the sharded connection pool, the callback is also
|
|
35
|
+
# passed a second argument, the requested server shard (generally a
|
|
36
|
+
# symbol), allowing for collection of per-shard telemetry:
|
|
37
|
+
#
|
|
38
|
+
# DB.pool.on_checkout_event = proc do |event, server|
|
|
39
|
+
# # ...
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# Note that the callback may be called currently by multiple threads.
|
|
43
|
+
# You should use some form of concurrency control inside the callback,
|
|
44
|
+
# such as a mutex or queue.
|
|
45
|
+
#
|
|
46
|
+
# Below is a brief example of usage to determine the percentage of
|
|
47
|
+
# connection requests where a connection was immediately available:
|
|
48
|
+
#
|
|
49
|
+
# mutex = Mutex.new
|
|
50
|
+
# total = immediates = 0
|
|
51
|
+
#
|
|
52
|
+
# DB.pool.on_checkout_event = proc do |event|
|
|
53
|
+
# case event
|
|
54
|
+
# when :immediately_available
|
|
55
|
+
# mutex.synchronize do
|
|
56
|
+
# total += 1
|
|
57
|
+
# immediates += 1
|
|
58
|
+
# end
|
|
59
|
+
# when :not_immediately_available
|
|
60
|
+
# mutex.synchronize do
|
|
61
|
+
# total += 1
|
|
62
|
+
# end
|
|
63
|
+
# end
|
|
64
|
+
# end
|
|
65
|
+
#
|
|
66
|
+
# immediate_percentage = lambda do
|
|
67
|
+
# mutex.synchronize do
|
|
68
|
+
# 100.0 * immediates / total
|
|
69
|
+
# end
|
|
70
|
+
# end
|
|
71
|
+
#
|
|
72
|
+
# Note that this extension only works with the timed_queue
|
|
73
|
+
# and sharded_timed_queue connection pools (the default
|
|
74
|
+
# connection pools when using Ruby 3.2+).
|
|
75
|
+
#
|
|
76
|
+
# Related modules: Sequel::ConnectionCheckoutEventCallbacks::TimedQueue,
|
|
77
|
+
# Sequel::ConnectionCheckoutEventCallbacks::ShardedTimedQueue
|
|
78
|
+
|
|
79
|
+
#
|
|
80
|
+
module Sequel
|
|
81
|
+
module ConnectionCheckoutEventCallbacks
|
|
82
|
+
module TimedQueue
|
|
83
|
+
# The callback that is called with connection checkout events.
|
|
84
|
+
attr_accessor :on_checkout_event
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def available
|
|
89
|
+
conn = super
|
|
90
|
+
@on_checkout_event.call(conn ? :immediately_available : :not_immediately_available)
|
|
91
|
+
conn
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def try_make_new
|
|
95
|
+
conn = super
|
|
96
|
+
@on_checkout_event.call(:new_connection) if conn
|
|
97
|
+
conn
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def wait_until_available
|
|
101
|
+
timer = Sequel.start_timer
|
|
102
|
+
conn = super
|
|
103
|
+
@on_checkout_event.call(Sequel.elapsed_seconds_since(timer))
|
|
104
|
+
conn
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
module ShardedTimedQueue
|
|
109
|
+
# The callback that is called with connection checkout events.
|
|
110
|
+
attr_accessor :on_checkout_event
|
|
111
|
+
|
|
112
|
+
private
|
|
113
|
+
|
|
114
|
+
def available(queue, server)
|
|
115
|
+
conn = super
|
|
116
|
+
@on_checkout_event.call(conn ? :immediately_available : :not_immediately_available, server)
|
|
117
|
+
conn
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def try_make_new(server)
|
|
121
|
+
conn = super
|
|
122
|
+
@on_checkout_event.call(:new_connection, server) if conn
|
|
123
|
+
conn
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def wait_until_available(queue, server)
|
|
127
|
+
timer = Sequel.start_timer
|
|
128
|
+
conn = super
|
|
129
|
+
@on_checkout_event.call(Sequel.elapsed_seconds_since(timer), server)
|
|
130
|
+
conn
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
default_callback = proc{}
|
|
136
|
+
|
|
137
|
+
Database.register_extension(:connection_checkout_event_callback) do |db|
|
|
138
|
+
pool = db.pool
|
|
139
|
+
|
|
140
|
+
case pool.pool_type
|
|
141
|
+
when :timed_queue
|
|
142
|
+
db.pool.extend(ConnectionCheckoutEventCallbacks::TimedQueue)
|
|
143
|
+
when :sharded_timed_queue
|
|
144
|
+
db.pool.extend(ConnectionCheckoutEventCallbacks::ShardedTimedQueue)
|
|
145
|
+
else
|
|
146
|
+
raise Error, "the connection_checkout_event_callback extension is only supported when using a timed_queue connection pool"
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
pool.on_checkout_event ||= default_callback
|
|
150
|
+
end
|
|
151
|
+
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module Plugins
|
|
5
|
+
# The detect_unnecessary_association_options plugin can detect unnecessary
|
|
6
|
+
# association options, and either warn or raise if they are detected.
|
|
7
|
+
# This allows you to find and remove the unnecessary options.
|
|
8
|
+
# Association options are considered unnecessary if they specify the same
|
|
9
|
+
# value as Sequel's defaults.
|
|
10
|
+
#
|
|
11
|
+
# To detect unnecessary association options, you should load the plugin
|
|
12
|
+
# into your model base class (e.g. Sequel::Model) before loading your model
|
|
13
|
+
# classes. Then, after all models have been loaded, you can call the
|
|
14
|
+
# detect_unnecessary_association_options on each to check for unnecessary
|
|
15
|
+
# association options. Additionally, if you are calling finalize_associations,
|
|
16
|
+
# it will automatically check for unnecessary association options.
|
|
17
|
+
#
|
|
18
|
+
# A typical usage would be to combine this with the subclasses plugin:
|
|
19
|
+
#
|
|
20
|
+
# Sequel::Model.plugin :detect_unnecessary_association_options
|
|
21
|
+
# Sequel::Model.plugin :subclasses
|
|
22
|
+
# # load model classes
|
|
23
|
+
#
|
|
24
|
+
# # implicitly check all subclasses when freezing descendants
|
|
25
|
+
# Sequel::Model.freeze_descendants
|
|
26
|
+
#
|
|
27
|
+
# # or, if not freezing all descendants
|
|
28
|
+
# Sequel::Model.descendants.each(&:detect_unnecessary_association_options)
|
|
29
|
+
#
|
|
30
|
+
# By default, the plugin warns for every unnecessary association option.
|
|
31
|
+
# To raise an error instead, you can pass the <tt>action: :raise</tt> option when loading the
|
|
32
|
+
# plugin:
|
|
33
|
+
#
|
|
34
|
+
# Sequel::Model.plugin :detect_unnecessary_association_options, action: :raise
|
|
35
|
+
#
|
|
36
|
+
# This plugin only detects the most common unnecessary association options, such as:
|
|
37
|
+
#
|
|
38
|
+
# * :class (all associations)
|
|
39
|
+
# * :key and :primary_key (associations without join tables)
|
|
40
|
+
# * :join_table, :left_key, :right_key, :left_primary_key, :right_primary_key (single join table associations)
|
|
41
|
+
# * :left_primary_key, :right_primary_key (*_through_many associations)
|
|
42
|
+
#
|
|
43
|
+
# Only association types supported by default or supported by a plugin that
|
|
44
|
+
# ships with Sequel are supported by this plugin. Other association types are
|
|
45
|
+
# ignored.
|
|
46
|
+
module DetectUnnecessaryAssociationOptions
|
|
47
|
+
def self.configure(model, opts={})
|
|
48
|
+
model.instance_variable_set(:@detect_unnecessary_association_options_action, opts[:action] || :warn)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Raised if the plugin action is to raise and an unnecessary association option
|
|
52
|
+
# is detected.
|
|
53
|
+
class UnnecessaryAssociationOption < Sequel::Error
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
module ClassMethods
|
|
57
|
+
Plugins.inherited_instance_variables(self, :@detect_unnecessary_association_options_action => nil)
|
|
58
|
+
|
|
59
|
+
# Implicitly check for unnecessary association options when finalizing associations.
|
|
60
|
+
def finalize_associations
|
|
61
|
+
res = super
|
|
62
|
+
detect_unnecessary_association_options
|
|
63
|
+
res
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Check for unnecessary association options.
|
|
67
|
+
def detect_unnecessary_association_options
|
|
68
|
+
@association_reflections.each_value do |ref|
|
|
69
|
+
meth = "detect_unnecessary_association_options_#{ref[:type]}"
|
|
70
|
+
# Expected to call private methods.
|
|
71
|
+
# Ignore unrecognized association types.
|
|
72
|
+
# External association types can define the appropriate method to
|
|
73
|
+
# support their own unnecessary association option checks.
|
|
74
|
+
if respond_to?(meth, true)
|
|
75
|
+
# All recognized association types need same class check
|
|
76
|
+
_detect_unnecessary_association_options_class(ref)
|
|
77
|
+
send(meth, ref)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
nil
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
# Action to take if an unnecessary association option is detected.
|
|
87
|
+
def unnecessary_association_options_detected(ref, key)
|
|
88
|
+
if @detect_unnecessary_association_options_action == :raise
|
|
89
|
+
raise UnnecessaryAssociationOption, "#{ref.inspect} :#{key} option unnecessary"
|
|
90
|
+
else
|
|
91
|
+
warn "#{ref.inspect} :#{key} option unnecessary"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Detect unnecessary :class option.
|
|
96
|
+
def _detect_unnecessary_association_options_class(ref)
|
|
97
|
+
return unless ref[:orig_class]
|
|
98
|
+
|
|
99
|
+
h = {}
|
|
100
|
+
name = ref[:name]
|
|
101
|
+
late_binding_class_option(h, ref.returns_array? ? singularize(name) : name)
|
|
102
|
+
|
|
103
|
+
begin
|
|
104
|
+
default_association_class = constantize(h[:class_name])
|
|
105
|
+
actual_association_class = ref.associated_class
|
|
106
|
+
rescue NameError
|
|
107
|
+
# Do not warn. For the default association class to not be a valid
|
|
108
|
+
# constant is expected. For the actual association class to not be
|
|
109
|
+
# a valid constant is not expected and a bug in the association, but
|
|
110
|
+
# the job of this plugin is not to detect invalid options, only
|
|
111
|
+
# unnecessary options.
|
|
112
|
+
else
|
|
113
|
+
if default_association_class.equal?(actual_association_class)
|
|
114
|
+
unnecessary_association_options_detected(ref, "class")
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Detect other unnecessary options. An option is considered unnecessary
|
|
120
|
+
# if the key was submitted as an association option and the value for
|
|
121
|
+
# the option is the same as the given value.
|
|
122
|
+
def _detect_unnecessary_association_options_key_value(ref, key, value)
|
|
123
|
+
if ref[:orig_opts].has_key?(key) && ref[:orig_opts][key] == value
|
|
124
|
+
unnecessary_association_options_detected(ref, key)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Same as _detect_unnecessary_association_options_key_value, but calls
|
|
129
|
+
# the default_* method on the association reflection to get the default value.
|
|
130
|
+
def _detect_unnecessary_association_options_key(ref, key)
|
|
131
|
+
_detect_unnecessary_association_options_key_value(ref, key, ref.send(:"default_#{key}"))
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def detect_unnecessary_association_options_many_to_one(ref)
|
|
135
|
+
_detect_unnecessary_association_options_key(ref, :key)
|
|
136
|
+
_detect_unnecessary_association_options_key_value(ref, :primary_key, ref.associated_class.primary_key)
|
|
137
|
+
end
|
|
138
|
+
alias detect_unnecessary_association_options_pg_array_to_many detect_unnecessary_association_options_many_to_one
|
|
139
|
+
|
|
140
|
+
def detect_unnecessary_association_options_one_to_many(ref)
|
|
141
|
+
_detect_unnecessary_association_options_key(ref, :key)
|
|
142
|
+
_detect_unnecessary_association_options_key_value(ref, :primary_key, primary_key)
|
|
143
|
+
end
|
|
144
|
+
alias detect_unnecessary_association_options_one_to_one detect_unnecessary_association_options_one_to_many
|
|
145
|
+
alias detect_unnecessary_association_options_many_to_pg_array detect_unnecessary_association_options_one_to_many
|
|
146
|
+
|
|
147
|
+
def detect_unnecessary_association_options_many_to_many(ref)
|
|
148
|
+
[:join_table, :left_key, :right_key].each do |key|
|
|
149
|
+
_detect_unnecessary_association_options_key(ref, key)
|
|
150
|
+
end
|
|
151
|
+
_detect_unnecessary_association_options_key_value(ref, :left_primary_key, primary_key)
|
|
152
|
+
_detect_unnecessary_association_options_key_value(ref, :right_primary_key, ref.associated_class.primary_key)
|
|
153
|
+
end
|
|
154
|
+
alias detect_unnecessary_association_options_one_through_one detect_unnecessary_association_options_many_to_many
|
|
155
|
+
|
|
156
|
+
def detect_unnecessary_association_options_many_through_many(ref)
|
|
157
|
+
_detect_unnecessary_association_options_key_value(ref, :left_primary_key, primary_key)
|
|
158
|
+
_detect_unnecessary_association_options_key_value(ref, :right_primary_key, ref.associated_class.primary_key)
|
|
159
|
+
end
|
|
160
|
+
alias detect_unnecessary_association_options_one_through_many detect_unnecessary_association_options_many_through_many
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
data/lib/sequel/version.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Sequel
|
|
|
6
6
|
|
|
7
7
|
# The minor version of Sequel. Bumped for every non-patch level
|
|
8
8
|
# release, generally around once a month.
|
|
9
|
-
MINOR =
|
|
9
|
+
MINOR = 102
|
|
10
10
|
|
|
11
11
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
|
12
12
|
# releases that fix regressions from previous versions.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sequel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.102.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeremy Evans
|
|
@@ -212,6 +212,7 @@ files:
|
|
|
212
212
|
- lib/sequel/extensions/blank.rb
|
|
213
213
|
- lib/sequel/extensions/caller_logging.rb
|
|
214
214
|
- lib/sequel/extensions/columns_introspection.rb
|
|
215
|
+
- lib/sequel/extensions/connection_checkout_event_callback.rb
|
|
215
216
|
- lib/sequel/extensions/connection_expiration.rb
|
|
216
217
|
- lib/sequel/extensions/connection_validator.rb
|
|
217
218
|
- lib/sequel/extensions/constant_sql_override.rb
|
|
@@ -344,6 +345,7 @@ files:
|
|
|
344
345
|
- lib/sequel/plugins/defaults_setter.rb
|
|
345
346
|
- lib/sequel/plugins/delay_add_association.rb
|
|
346
347
|
- lib/sequel/plugins/deprecated_associations.rb
|
|
348
|
+
- lib/sequel/plugins/detect_unnecessary_association_options.rb
|
|
347
349
|
- lib/sequel/plugins/dirty.rb
|
|
348
350
|
- lib/sequel/plugins/eager_each.rb
|
|
349
351
|
- lib/sequel/plugins/eager_graph_eager.rb
|