activerecord 6.1.2 → 6.1.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +180 -2
- data/lib/active_record/associations/association.rb +7 -1
- data/lib/active_record/associations/belongs_to_association.rb +1 -2
- data/lib/active_record/coders/yaml_column.rb +11 -1
- data/lib/active_record/connection_adapters.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/transaction.rb +14 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +5 -5
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +10 -6
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +6 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +17 -2
- data/lib/active_record/connection_adapters/pool_manager.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -5
- data/lib/active_record/connection_adapters/schema_cache.rb +9 -1
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +0 -2
- data/lib/active_record/connection_handling.rb +9 -9
- data/lib/active_record/core.rb +16 -5
- data/lib/active_record/enum.rb +4 -6
- data/lib/active_record/fixtures.rb +1 -1
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/insert_all.rb +5 -1
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/model_schema.rb +4 -4
- data/lib/active_record/railties/databases.rake +3 -2
- data/lib/active_record/relation.rb +10 -17
- data/lib/active_record/relation/calculations.rb +6 -2
- data/lib/active_record/relation/finder_methods.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +3 -1
- data/lib/active_record/relation/query_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +17 -14
- data/lib/active_record/scoping/default.rb +1 -3
- data/lib/active_record/statement_cache.rb +2 -2
- data/lib/active_record/test_fixtures.rb +42 -1
- data/lib/active_record/validations/numericality.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/composite.rb +3 -3
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/nodes/homogeneous_in.rb +4 -0
- data/lib/arel/predications.rb +2 -2
- data/lib/arel/visitors/to_sql.rb +1 -1
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8533ac44f34eb20fbdc7d86aeef22c966a16ebe23e157db652a5bc1d6551429a
|
4
|
+
data.tar.gz: 2fe7a2768e779b4b5cd02f9da33231392199313c9acd4a2600a7b10f253ac7bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e65080023ad359f9782e8c9f40437e0fb961b285cbe9e9ecb8efb8155defd814470a774ef086b5b9911de1c60cb7aa04e4f0006cdaa361344dfb41627f2a3fd3
|
7
|
+
data.tar.gz: 3c7e9ac5eea68d2e2ed2d4c6bc6a49f59b026682da56a695426454e20b6f4d25bb1d1dec4ecf651fbf42bce7231cf97a2cbf45751632471ffb7ffe3a6382a460
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,181 @@
|
|
1
|
+
## Rails 6.1.4 (June 24, 2021) ##
|
2
|
+
|
3
|
+
* Do not try to rollback transactions that failed due to a `ActiveRecord::TransactionRollbackError`.
|
4
|
+
|
5
|
+
*Jamie McCarthy*
|
6
|
+
|
7
|
+
* Raise an error if `pool_config` is `nil` in `set_pool_config`.
|
8
|
+
|
9
|
+
*Eileen M. Uchitelle*
|
10
|
+
|
11
|
+
* Fix compatibility with `psych >= 4`.
|
12
|
+
|
13
|
+
Starting in Psych 4.0.0 `YAML.load` behaves like `YAML.safe_load`. To preserve compatibility
|
14
|
+
Active Record's schema cache loader and `YAMLColumn` now uses `YAML.unsafe_load` if available.
|
15
|
+
|
16
|
+
*Jean Boussier*
|
17
|
+
|
18
|
+
* Support using replicas when using `rails dbconsole`.
|
19
|
+
|
20
|
+
*Christopher Thornton*
|
21
|
+
|
22
|
+
* Restore connection pools after transactional tests.
|
23
|
+
|
24
|
+
*Eugene Kenny*
|
25
|
+
|
26
|
+
* Change `upsert_all` to fails cleanly for MySQL when `:unique_by` is used.
|
27
|
+
|
28
|
+
*Bastian Bartmann*
|
29
|
+
|
30
|
+
* Fix user-defined `self.default_scope` to respect table alias.
|
31
|
+
|
32
|
+
*Ryuta Kamizono*
|
33
|
+
|
34
|
+
* Clear `@cache_keys` cache after `update_all`, `delete_all`, `destroy_all`.
|
35
|
+
|
36
|
+
*Ryuta Kamizono*
|
37
|
+
|
38
|
+
* Changed Arel predications `contains` and `overlaps` to use
|
39
|
+
`quoted_node` so that PostgreSQL arrays are quoted properly.
|
40
|
+
|
41
|
+
*Bradley Priest*
|
42
|
+
|
43
|
+
* Fix `merge` when the `where` clauses have string contents.
|
44
|
+
|
45
|
+
*Ryuta Kamizono*
|
46
|
+
|
47
|
+
* Fix rollback of parent destruction with nested `dependent: :destroy`.
|
48
|
+
|
49
|
+
*Jacopo Beschi*
|
50
|
+
|
51
|
+
* Fix binds logging for `"WHERE ... IN ..."` statements.
|
52
|
+
|
53
|
+
*Ricardo Díaz*
|
54
|
+
|
55
|
+
* Handle `false` in relation strict loading checks.
|
56
|
+
|
57
|
+
Previously when a model had strict loading set to true and then had a
|
58
|
+
relation set `strict_loading` to false the false wasn't considered when
|
59
|
+
deciding whether to raise/warn about strict loading.
|
60
|
+
|
61
|
+
```
|
62
|
+
class Dog < ActiveRecord::Base
|
63
|
+
self.strict_loading_by_default = true
|
64
|
+
|
65
|
+
has_many :treats, strict_loading: false
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
In the example, `dog.treats` would still raise even though
|
70
|
+
`strict_loading` was set to false. This is a bug effecting more than
|
71
|
+
Active Storage which is why I made this PR superceeding #41461. We need
|
72
|
+
to fix this for all applications since the behavior is a little
|
73
|
+
surprising. I took the test from ##41461 and the code suggestion from #41453
|
74
|
+
with some additions.
|
75
|
+
|
76
|
+
*Eileen M. Uchitelle*, *Radamés Roriz*
|
77
|
+
|
78
|
+
* Fix numericality validator without precision.
|
79
|
+
|
80
|
+
*Ryuta Kamizono*
|
81
|
+
|
82
|
+
* Fix aggregate attribute on Enum types.
|
83
|
+
|
84
|
+
*Ryuta Kamizono*
|
85
|
+
|
86
|
+
* Fix `CREATE INDEX` statement generation for PostgreSQL.
|
87
|
+
|
88
|
+
*eltongo*
|
89
|
+
|
90
|
+
* Fix where clause on enum attribute when providing array of strings.
|
91
|
+
|
92
|
+
*Ryuta Kamizono*
|
93
|
+
|
94
|
+
* Fix `unprepared_statement` to work it when nesting.
|
95
|
+
|
96
|
+
*Ryuta Kamizono*
|
97
|
+
|
98
|
+
|
99
|
+
## Rails 6.1.3.2 (May 05, 2021) ##
|
100
|
+
|
101
|
+
* No changes.
|
102
|
+
|
103
|
+
|
104
|
+
## Rails 6.1.3.1 (March 26, 2021) ##
|
105
|
+
|
106
|
+
* No changes.
|
107
|
+
|
108
|
+
|
109
|
+
## Rails 6.1.3 (February 17, 2021) ##
|
110
|
+
|
111
|
+
* Fix the MySQL adapter to always set the right collation and charset
|
112
|
+
to the connection session.
|
113
|
+
|
114
|
+
*Rafael Mendonça França*
|
115
|
+
|
116
|
+
* Fix MySQL adapter handling of time objects when prepared statements
|
117
|
+
are enabled.
|
118
|
+
|
119
|
+
*Rafael Mendonça França*
|
120
|
+
|
121
|
+
* Fix scoping in enum fields using conditions that would generate
|
122
|
+
an `IN` clause.
|
123
|
+
|
124
|
+
*Ryuta Kamizono*
|
125
|
+
|
126
|
+
* Skip optimised #exist? query when #include? is called on a relation
|
127
|
+
with a having clause
|
128
|
+
|
129
|
+
Relations that have aliased select values AND a having clause that
|
130
|
+
references an aliased select value would generate an error when
|
131
|
+
#include? was called, due to an optimisation that would generate
|
132
|
+
call #exists? on the relation instead, which effectively alters
|
133
|
+
the select values of the query (and thus removes the aliased select
|
134
|
+
values), but leaves the having clause intact. Because the having
|
135
|
+
clause is then referencing an aliased column that is no longer
|
136
|
+
present in the simplified query, an ActiveRecord::InvalidStatement
|
137
|
+
error was raised.
|
138
|
+
|
139
|
+
An sample query affected by this problem:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
Author.select('COUNT(*) as total_posts', 'authors.*')
|
143
|
+
.joins(:posts)
|
144
|
+
.group(:id)
|
145
|
+
.having('total_posts > 2')
|
146
|
+
.include?(Author.first)
|
147
|
+
```
|
148
|
+
|
149
|
+
This change adds an addition check to the condition that skips the
|
150
|
+
simplified #exists? query, which simply checks for the presence of
|
151
|
+
a having clause.
|
152
|
+
|
153
|
+
Fixes #41417
|
154
|
+
|
155
|
+
*Michael Smart*
|
156
|
+
|
157
|
+
* Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
|
158
|
+
without Rails knowledge (e.g., if app gets kill -9d during long-running query or due to Rack::Timeout), app won't end
|
159
|
+
up in perpetual crash state for being inconsistent with Postgres.
|
160
|
+
|
161
|
+
*wbharding*, *Martin Tepper*
|
162
|
+
|
163
|
+
|
164
|
+
## Rails 6.1.2.1 (February 10, 2021) ##
|
165
|
+
|
166
|
+
* Fix possible DoS vector in PostgreSQL money type
|
167
|
+
|
168
|
+
Carefully crafted input can cause a DoS via the regular expressions used
|
169
|
+
for validating the money format in the PostgreSQL adapter. This patch
|
170
|
+
fixes the regexp.
|
171
|
+
|
172
|
+
Thanks to @dee-see from Hackerone for this patch!
|
173
|
+
|
174
|
+
[CVE-2021-22880]
|
175
|
+
|
176
|
+
*Aaron Patterson*
|
177
|
+
|
178
|
+
|
1
179
|
## Rails 6.1.2 (February 09, 2021) ##
|
2
180
|
|
3
181
|
* Fix timestamp type for sqlite3.
|
@@ -973,14 +1151,14 @@
|
|
973
1151
|
Deprecated behavior:
|
974
1152
|
|
975
1153
|
```ruby
|
976
|
-
db_config = ActiveRecord::Base.configs_for(env_name: "development", spec_name: "primary")
|
1154
|
+
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "development", spec_name: "primary")
|
977
1155
|
db_config.spec_name
|
978
1156
|
```
|
979
1157
|
|
980
1158
|
New behavior:
|
981
1159
|
|
982
1160
|
```ruby
|
983
|
-
db_config = ActiveRecord::Base.configs_for(env_name: "development", name: "primary")
|
1161
|
+
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "development", name: "primary")
|
984
1162
|
db_config.name
|
985
1163
|
```
|
986
1164
|
|
@@ -211,7 +211,7 @@ module ActiveRecord
|
|
211
211
|
|
212
212
|
private
|
213
213
|
def find_target
|
214
|
-
if
|
214
|
+
if strict_loading? && owner.validation_context.nil?
|
215
215
|
Base.strict_loading_violation!(owner: owner.class, reflection: reflection)
|
216
216
|
end
|
217
217
|
|
@@ -227,6 +227,12 @@ module ActiveRecord
|
|
227
227
|
sc.execute(binds, klass.connection) { |record| set_inverse_instance(record) }
|
228
228
|
end
|
229
229
|
|
230
|
+
def strict_loading?
|
231
|
+
return reflection.strict_loading? if reflection.options.key?(:strict_loading)
|
232
|
+
|
233
|
+
owner.strict_loading?
|
234
|
+
end
|
235
|
+
|
230
236
|
# The scope for this association.
|
231
237
|
#
|
232
238
|
# Note that the association_scope is merged into the target_scope only when the
|
@@ -9,8 +9,7 @@ module ActiveRecord
|
|
9
9
|
|
10
10
|
case options[:dependent]
|
11
11
|
when :destroy
|
12
|
-
target.destroy
|
13
|
-
raise ActiveRecord::Rollback unless target.destroyed?
|
12
|
+
raise ActiveRecord::Rollback unless target.destroy
|
14
13
|
when :destroy_async
|
15
14
|
id = owner.public_send(reflection.foreign_key.to_sym)
|
16
15
|
primary_key_column = reflection.active_record_primary_key.to_sym
|
@@ -23,7 +23,7 @@ module ActiveRecord
|
|
23
23
|
def load(yaml)
|
24
24
|
return object_class.new if object_class != Object && yaml.nil?
|
25
25
|
return yaml unless yaml.is_a?(String) && yaml.start_with?("---")
|
26
|
-
obj =
|
26
|
+
obj = yaml_load(yaml)
|
27
27
|
|
28
28
|
assert_valid_value(obj, action: "load")
|
29
29
|
obj ||= object_class.new if object_class != Object
|
@@ -44,6 +44,16 @@ module ActiveRecord
|
|
44
44
|
rescue ArgumentError
|
45
45
|
raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
|
46
46
|
end
|
47
|
+
|
48
|
+
if YAML.respond_to?(:unsafe_load)
|
49
|
+
def yaml_load(payload)
|
50
|
+
YAML.unsafe_load(payload)
|
51
|
+
end
|
52
|
+
else
|
53
|
+
def yaml_load(payload)
|
54
|
+
YAML.load(payload)
|
55
|
+
end
|
56
|
+
end
|
47
57
|
end
|
48
58
|
end
|
49
59
|
end
|
@@ -12,6 +12,8 @@ module ActiveRecord
|
|
12
12
|
autoload :PoolConfig
|
13
13
|
autoload :PoolManager
|
14
14
|
autoload :LegacyPoolManager
|
15
|
+
autoload :SchemaCache
|
16
|
+
autoload :Deduplicable
|
15
17
|
|
16
18
|
autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
|
17
19
|
autoload :IndexDefinition
|
@@ -395,7 +395,7 @@ module ActiveRecord
|
|
395
395
|
|
396
396
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
397
397
|
# something beyond a simple insert (e.g. Oracle).
|
398
|
-
# Most of adapters should implement
|
398
|
+
# Most of adapters should implement +insert_fixtures_set+ that leverages bulk SQL insert.
|
399
399
|
# We keep this method to provide fallback
|
400
400
|
# for databases like sqlite that do not support bulk inserts.
|
401
401
|
def insert_fixture(fixture, table_name)
|
@@ -94,8 +94,8 @@ module ActiveRecord
|
|
94
94
|
sql = ["CREATE"]
|
95
95
|
sql << "UNIQUE" if index.unique
|
96
96
|
sql << "INDEX"
|
97
|
-
sql << "IF NOT EXISTS" if o.if_not_exists
|
98
97
|
sql << o.algorithm if o.algorithm
|
98
|
+
sql << "IF NOT EXISTS" if o.if_not_exists
|
99
99
|
sql << index.type if index.type
|
100
100
|
sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
|
101
101
|
sql << "USING #{index.using}" if supports_index_using? && index.using
|
@@ -33,6 +33,10 @@ module ActiveRecord
|
|
33
33
|
@state == :fully_rolledback
|
34
34
|
end
|
35
35
|
|
36
|
+
def invalidated?
|
37
|
+
@state == :invalidated
|
38
|
+
end
|
39
|
+
|
36
40
|
def fully_completed?
|
37
41
|
completed?
|
38
42
|
end
|
@@ -51,6 +55,11 @@ module ActiveRecord
|
|
51
55
|
@state = :fully_rolledback
|
52
56
|
end
|
53
57
|
|
58
|
+
def invalidate!
|
59
|
+
@children&.each { |c| c.invalidate! }
|
60
|
+
@state = :invalidated
|
61
|
+
end
|
62
|
+
|
54
63
|
def commit!
|
55
64
|
@state = :committed
|
56
65
|
end
|
@@ -299,7 +308,7 @@ module ActiveRecord
|
|
299
308
|
def rollback_transaction(transaction = nil)
|
300
309
|
@connection.lock.synchronize do
|
301
310
|
transaction ||= @stack.pop
|
302
|
-
transaction.rollback
|
311
|
+
transaction.rollback unless transaction.state.invalidated?
|
303
312
|
transaction.rollback_records
|
304
313
|
end
|
305
314
|
end
|
@@ -312,15 +321,17 @@ module ActiveRecord
|
|
312
321
|
ret
|
313
322
|
rescue Exception => error
|
314
323
|
if transaction
|
324
|
+
transaction.state.invalidate! if error.is_a? ActiveRecord::TransactionRollbackError
|
315
325
|
rollback_transaction
|
316
326
|
after_failure_actions(transaction, error)
|
317
327
|
end
|
328
|
+
|
318
329
|
raise
|
319
330
|
ensure
|
320
331
|
if transaction
|
321
332
|
if error
|
322
|
-
# @connection still holds an open transaction, so we must not
|
323
|
-
# put it back in the pool for reuse
|
333
|
+
# @connection still holds an open or invalid transaction, so we must not
|
334
|
+
# put it back in the pool for reuse.
|
324
335
|
@connection.throw_away! unless transaction.state.rolledback?
|
325
336
|
else
|
326
337
|
if Thread.current.status == "aborting"
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "set"
|
4
|
-
require "active_record/connection_adapters/schema_cache"
|
5
4
|
require "active_record/connection_adapters/sql_type_metadata"
|
6
5
|
require "active_record/connection_adapters/abstract/schema_dumper"
|
7
6
|
require "active_record/connection_adapters/abstract/schema_creation"
|
@@ -116,10 +115,10 @@ module ActiveRecord
|
|
116
115
|
# Returns true if the connection is a replica.
|
117
116
|
#
|
118
117
|
# If the application is using legacy handling, returns
|
119
|
-
# true if
|
118
|
+
# true if +connection_handler.prevent_writes+ is set.
|
120
119
|
#
|
121
120
|
# If the application is using the new connection handling
|
122
|
-
# will return true based on
|
121
|
+
# will return true based on +current_preventing_writes+.
|
123
122
|
def preventing_writes?
|
124
123
|
return true if replica?
|
125
124
|
return ActiveRecord::Base.connection_handler.prevent_writes if ActiveRecord::Base.legacy_connection_handling
|
@@ -154,9 +153,10 @@ module ActiveRecord
|
|
154
153
|
end
|
155
154
|
end
|
156
155
|
|
157
|
-
def prepared_statements
|
156
|
+
def prepared_statements?
|
158
157
|
@prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
|
159
158
|
end
|
159
|
+
alias :prepared_statements :prepared_statements?
|
160
160
|
|
161
161
|
def prepared_statements_disabled_cache # :nodoc:
|
162
162
|
Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new
|
@@ -250,7 +250,7 @@ module ActiveRecord
|
|
250
250
|
end
|
251
251
|
|
252
252
|
def unprepared_statement
|
253
|
-
cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
|
253
|
+
cache = prepared_statements_disabled_cache.add?(object_id) if @prepared_statements
|
254
254
|
yield
|
255
255
|
ensure
|
256
256
|
cache&.delete(object_id)
|
@@ -751,11 +751,6 @@ module ActiveRecord
|
|
751
751
|
wait_timeout = 2147483 unless wait_timeout.is_a?(Integer)
|
752
752
|
variables["wait_timeout"] = wait_timeout
|
753
753
|
|
754
|
-
# Set the collation of the connection character set.
|
755
|
-
if @config[:collation]
|
756
|
-
variables["collation_connection"] = @config[:collation]
|
757
|
-
end
|
758
|
-
|
759
754
|
defaults = [":default", :default].to_set
|
760
755
|
|
761
756
|
# Make MySQL reject illegal values rather than truncating or blanking them, see
|
@@ -775,6 +770,15 @@ module ActiveRecord
|
|
775
770
|
end
|
776
771
|
sql_mode_assignment = "@@SESSION.sql_mode = #{sql_mode}, " if sql_mode
|
777
772
|
|
773
|
+
# NAMES does not have an equals sign, see
|
774
|
+
# https://dev.mysql.com/doc/refman/en/set-names.html
|
775
|
+
# (trailing comma because variable_assignments will always have content)
|
776
|
+
if @config[:encoding]
|
777
|
+
encoding = +"NAMES #{@config[:encoding]}"
|
778
|
+
encoding << " COLLATE #{@config[:collation]}" if @config[:collation]
|
779
|
+
encoding << ", "
|
780
|
+
end
|
781
|
+
|
778
782
|
# Gather up all of the SET variables...
|
779
783
|
variable_assignments = variables.map do |k, v|
|
780
784
|
if defaults.include?(v)
|
@@ -786,7 +790,7 @@ module ActiveRecord
|
|
786
790
|
end.compact.join(", ")
|
787
791
|
|
788
792
|
# ...and send them all in one query
|
789
|
-
execute("SET #{sql_mode_assignment} #{variable_assignments}", "SCHEMA")
|
793
|
+
execute("SET #{encoding} #{sql_mode_assignment} #{variable_assignments}", "SCHEMA")
|
790
794
|
end
|
791
795
|
|
792
796
|
def column_definitions(table_name) # :nodoc:
|
@@ -23,8 +23,12 @@ module ActiveRecord
|
|
23
23
|
@name_to_pool_config[shard]
|
24
24
|
end
|
25
25
|
|
26
|
-
def set_pool_config(
|
27
|
-
|
26
|
+
def set_pool_config(role, shard, pool_config)
|
27
|
+
if pool_config
|
28
|
+
@name_to_pool_config[shard] = pool_config
|
29
|
+
else
|
30
|
+
raise ArgumentError, "The `pool_config` for the :#{role} role and :#{shard} shard was `nil`. Please check your configuration. If you want your writing role to be something other than `:writing` set `config.active_record.writing_role` in your application configuration. The same setting should be applied for the `reading_role` if applicable."
|
31
|
+
end
|
28
32
|
end
|
29
33
|
end
|
30
34
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/time_with_zone"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters
|
5
7
|
module MySQL
|
@@ -69,10 +71,23 @@ module ActiveRecord
|
|
69
71
|
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
70
72
|
|
71
73
|
private
|
74
|
+
# Override +_type_cast+ we pass to mysql2 Date and Time objects instead
|
75
|
+
# of Strings since mysql2 is able to handle those classes more efficiently.
|
72
76
|
def _type_cast(value)
|
73
77
|
case value
|
74
|
-
when
|
75
|
-
|
78
|
+
when ActiveSupport::TimeWithZone
|
79
|
+
# We need to check explicitly for ActiveSupport::TimeWithZone because
|
80
|
+
# we need to transform it to Time objects but we don't want to
|
81
|
+
# transform Time objects to themselves.
|
82
|
+
if ActiveRecord::Base.default_timezone == :utc
|
83
|
+
value.getutc
|
84
|
+
else
|
85
|
+
value.getlocal
|
86
|
+
end
|
87
|
+
when Date, Time
|
88
|
+
value
|
89
|
+
else
|
90
|
+
super
|
76
91
|
end
|
77
92
|
end
|
78
93
|
end
|
@@ -36,7 +36,11 @@ module ActiveRecord
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def set_pool_config(role, shard, pool_config)
|
39
|
-
|
39
|
+
if pool_config
|
40
|
+
@name_to_role_mapping[role][shard] = pool_config
|
41
|
+
else
|
42
|
+
raise ArgumentError, "The `pool_config` for the :#{role} role and :#{shard} shard was `nil`. Please check your configuration. If you want your writing role to be something other than `:writing` set `config.active_record.writing_role` in your application configuration. The same setting should be applied for the `reading_role` if applicable."
|
43
|
+
end
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
@@ -26,9 +26,9 @@ module ActiveRecord
|
|
26
26
|
|
27
27
|
value = value.sub(/^\((.+)\)$/, '-\1') # (4)
|
28
28
|
case value
|
29
|
-
when /^-?\D
|
29
|
+
when /^-?\D*+[\d,]+\.\d{2}$/ # (1)
|
30
30
|
value.gsub!(/[^-\d.]/, "")
|
31
|
-
when /^-?\D
|
31
|
+
when /^-?\D*+[\d.]+,\d{2}$/ # (2)
|
32
32
|
value.gsub!(/[^-\d,]/, "").sub!(/,/, ".")
|
33
33
|
end
|
34
34
|
|
@@ -9,7 +9,15 @@ module ActiveRecord
|
|
9
9
|
return unless File.file?(filename)
|
10
10
|
|
11
11
|
read(filename) do |file|
|
12
|
-
filename.include?(".dump")
|
12
|
+
if filename.include?(".dump")
|
13
|
+
Marshal.load(file)
|
14
|
+
else
|
15
|
+
if YAML.respond_to?(:unsafe_load)
|
16
|
+
YAML.unsafe_load(file)
|
17
|
+
else
|
18
|
+
YAML.load(file)
|
19
|
+
end
|
20
|
+
end
|
13
21
|
end
|
14
22
|
end
|
15
23
|
|
@@ -114,7 +114,7 @@ module ActiveRecord
|
|
114
114
|
#
|
115
115
|
# If only a role is passed, Active Record will look up the connection
|
116
116
|
# based on the requested role. If a non-established role is requested
|
117
|
-
# an
|
117
|
+
# an +ActiveRecord::ConnectionNotEstablished+ error will be raised:
|
118
118
|
#
|
119
119
|
# ActiveRecord::Base.connected_to(role: :writing) do
|
120
120
|
# Dog.create! # creates dog using dog writing connection
|
@@ -125,7 +125,7 @@ module ActiveRecord
|
|
125
125
|
# end
|
126
126
|
#
|
127
127
|
# When swapping to a shard, the role must be passed as well. If a non-existent
|
128
|
-
# shard is passed, an
|
128
|
+
# shard is passed, an +ActiveRecord::ConnectionNotEstablished+ error will be
|
129
129
|
# raised.
|
130
130
|
#
|
131
131
|
# When a shard and role is passed, Active Record will first lookup the role,
|
@@ -178,11 +178,11 @@ module ActiveRecord
|
|
178
178
|
end
|
179
179
|
end
|
180
180
|
|
181
|
-
# Connects a role and/or shard to the provided connection names. Optionally
|
182
|
-
# can be passed to block writes on a connection.
|
183
|
-
#
|
181
|
+
# Connects a role and/or shard to the provided connection names. Optionally +prevent_writes+
|
182
|
+
# can be passed to block writes on a connection. +reading+ will automatically set
|
183
|
+
# +prevent_writes+ to true.
|
184
184
|
#
|
185
|
-
#
|
185
|
+
# +connected_to_many+ is an alternative to deeply nested +connected_to+ blocks.
|
186
186
|
#
|
187
187
|
# Usage:
|
188
188
|
#
|
@@ -216,7 +216,7 @@ module ActiveRecord
|
|
216
216
|
# being used. For example, when booting a console in readonly mode.
|
217
217
|
#
|
218
218
|
# It is not recommended to use this method in a request since it
|
219
|
-
# does not yield to a block like
|
219
|
+
# does not yield to a block like +connected_to+.
|
220
220
|
def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
|
221
221
|
if legacy_connection_handling
|
222
222
|
raise NotImplementedError, "`connecting_to` is not available with `legacy_connection_handling`."
|
@@ -230,13 +230,13 @@ module ActiveRecord
|
|
230
230
|
# Prevent writing to the database regardless of role.
|
231
231
|
#
|
232
232
|
# In some cases you may want to prevent writes to the database
|
233
|
-
# even if you are on a database that can write.
|
233
|
+
# even if you are on a database that can write. +while_preventing_writes+
|
234
234
|
# will prevent writes to the database for the duration of the block.
|
235
235
|
#
|
236
236
|
# This method does not provide the same protection as a readonly
|
237
237
|
# user and is meant to be a safeguard against accidental writes.
|
238
238
|
#
|
239
|
-
# See
|
239
|
+
# See +READ_QUERY+ for the queries that are blocked by this
|
240
240
|
# method.
|
241
241
|
def while_preventing_writes(enabled = true, &block)
|
242
242
|
if legacy_connection_handling
|
data/lib/active_record/core.rb
CHANGED
@@ -408,7 +408,21 @@ module ActiveRecord
|
|
408
408
|
end
|
409
409
|
|
410
410
|
# Specifies columns which shouldn't be exposed while calling +#inspect+.
|
411
|
-
|
411
|
+
def filter_attributes=(filter_attributes)
|
412
|
+
@inspection_filter = nil
|
413
|
+
@filter_attributes = filter_attributes
|
414
|
+
end
|
415
|
+
|
416
|
+
def inspection_filter # :nodoc:
|
417
|
+
if defined?(@filter_attributes)
|
418
|
+
@inspection_filter ||= begin
|
419
|
+
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
420
|
+
ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
|
421
|
+
end
|
422
|
+
else
|
423
|
+
superclass.inspection_filter
|
424
|
+
end
|
425
|
+
end
|
412
426
|
|
413
427
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
414
428
|
def inspect # :nodoc:
|
@@ -776,10 +790,7 @@ module ActiveRecord
|
|
776
790
|
private_constant :InspectionMask
|
777
791
|
|
778
792
|
def inspection_filter
|
779
|
-
|
780
|
-
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
781
|
-
ActiveSupport::ParameterFilter.new(self.class.filter_attributes, mask: mask)
|
782
|
-
end
|
793
|
+
self.class.inspection_filter
|
783
794
|
end
|
784
795
|
end
|
785
796
|
end
|
data/lib/active_record/enum.rb
CHANGED
@@ -139,22 +139,20 @@ module ActiveRecord
|
|
139
139
|
mapping.key(subtype.deserialize(value))
|
140
140
|
end
|
141
141
|
|
142
|
-
def serializable?(value)
|
143
|
-
(value.blank? || mapping.has_key?(value) || mapping.has_value?(value)) && super
|
144
|
-
end
|
145
|
-
|
146
142
|
def serialize(value)
|
147
143
|
mapping.fetch(value, value)
|
148
144
|
end
|
149
145
|
|
150
146
|
def assert_valid_value(value)
|
151
|
-
unless
|
147
|
+
unless value.blank? || mapping.has_key?(value) || mapping.has_value?(value)
|
152
148
|
raise ArgumentError, "'#{value}' is not a valid #{name}"
|
153
149
|
end
|
154
150
|
end
|
155
151
|
|
152
|
+
attr_reader :subtype
|
153
|
+
|
156
154
|
private
|
157
|
-
attr_reader :name, :mapping
|
155
|
+
attr_reader :name, :mapping
|
158
156
|
end
|
159
157
|
|
160
158
|
def enum(definitions)
|
@@ -181,7 +181,7 @@ module ActiveRecord
|
|
181
181
|
# end
|
182
182
|
# end
|
183
183
|
#
|
184
|
-
# If you preload your test database with all fixture data (probably by running
|
184
|
+
# If you preload your test database with all fixture data (probably by running <tt>bin/rails db:fixtures:load</tt>)
|
185
185
|
# and use transactional tests, then you may omit all fixtures declarations in your test cases since
|
186
186
|
# all the data's already there and every case rolls back its changes.
|
187
187
|
#
|
@@ -69,7 +69,11 @@ module ActiveRecord
|
|
69
69
|
attr_reader :scope_attributes
|
70
70
|
|
71
71
|
def find_unique_index_for(unique_by)
|
72
|
-
|
72
|
+
if !connection.supports_insert_conflict_target?
|
73
|
+
return if unique_by.nil?
|
74
|
+
|
75
|
+
raise ArgumentError, "#{connection.class} does not support :unique_by"
|
76
|
+
end
|
73
77
|
|
74
78
|
name_or_columns = unique_by || model.primary_key
|
75
79
|
match = Array(name_or_columns).map(&:to_s)
|
@@ -320,7 +320,7 @@ module ActiveRecord
|
|
320
320
|
# +table_name+. Passing a hash containing <tt>:from</tt> and <tt>:to</tt>
|
321
321
|
# as +default_or_changes+ will make this change reversible in the migration.
|
322
322
|
# * <tt>change_column_null(table_name, column_name, null, default = nil)</tt>:
|
323
|
-
# Sets or removes a
|
323
|
+
# Sets or removes a <tt>NOT NULL</tt> constraint on +column_name+. The +null+ flag
|
324
324
|
# indicates whether the value can be +NULL+. See
|
325
325
|
# ActiveRecord::ConnectionAdapters::SchemaStatements#change_column_null for
|
326
326
|
# details.
|
@@ -122,9 +122,9 @@ module ActiveRecord
|
|
122
122
|
# :singleton-method: immutable_strings_by_default=
|
123
123
|
# :call-seq: immutable_strings_by_default=(bool)
|
124
124
|
#
|
125
|
-
# Determines whether columns should infer their type as
|
126
|
-
#
|
127
|
-
#
|
125
|
+
# Determines whether columns should infer their type as +:string+ or
|
126
|
+
# +:immutable_string+. This setting does not affect the behavior of
|
127
|
+
# <tt>attribute :foo, :string</tt>. Defaults to false.
|
128
128
|
|
129
129
|
included do
|
130
130
|
mattr_accessor :primary_key_prefix_type, instance_writer: false
|
@@ -316,7 +316,7 @@ module ActiveRecord
|
|
316
316
|
# self.ignored_columns = [:category]
|
317
317
|
# end
|
318
318
|
#
|
319
|
-
# The schema still contains
|
319
|
+
# The schema still contains "category", but now the model omits it, so any meta-driven code or
|
320
320
|
# schema caching will not attempt to use the column:
|
321
321
|
#
|
322
322
|
# Project.columns_hash["category"] => nil
|
@@ -413,8 +413,9 @@ db_namespace = namespace :db do
|
|
413
413
|
fixture_files = if ENV["FIXTURES"]
|
414
414
|
ENV["FIXTURES"].split(",")
|
415
415
|
else
|
416
|
-
|
417
|
-
|
416
|
+
files = Dir[File.join(fixtures_dir, "**/*.{yml}")]
|
417
|
+
files.reject! { |f| f.start_with?(File.join(fixtures_dir, "files")) }
|
418
|
+
files.map! { |f| f[fixtures_dir.to_s.size..-5].delete_prefix("/") }
|
418
419
|
end
|
419
420
|
|
420
421
|
ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_files)
|
@@ -440,13 +440,11 @@ module ActiveRecord
|
|
440
440
|
def update_all(updates)
|
441
441
|
raise ArgumentError, "Empty list of attributes to change" if updates.blank?
|
442
442
|
|
443
|
-
|
444
|
-
|
445
|
-
return relation.update_all(updates)
|
446
|
-
end
|
443
|
+
arel = eager_loading? ? apply_join_dependency.arel : build_arel
|
444
|
+
arel.source.left = table
|
447
445
|
|
448
446
|
stmt = Arel::UpdateManager.new
|
449
|
-
stmt.table(arel.
|
447
|
+
stmt.table(arel.source)
|
450
448
|
stmt.key = table[primary_key]
|
451
449
|
stmt.take(arel.limit)
|
452
450
|
stmt.offset(arel.offset)
|
@@ -465,7 +463,7 @@ module ActiveRecord
|
|
465
463
|
stmt.set Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name))
|
466
464
|
end
|
467
465
|
|
468
|
-
|
466
|
+
klass.connection.update(stmt, "#{klass} Update All").tap { reset }
|
469
467
|
end
|
470
468
|
|
471
469
|
def update(id = :all, attributes) # :nodoc:
|
@@ -582,23 +580,18 @@ module ActiveRecord
|
|
582
580
|
raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
|
583
581
|
end
|
584
582
|
|
585
|
-
|
586
|
-
|
587
|
-
return relation.delete_all
|
588
|
-
end
|
583
|
+
arel = eager_loading? ? apply_join_dependency.arel : build_arel
|
584
|
+
arel.source.left = table
|
589
585
|
|
590
586
|
stmt = Arel::DeleteManager.new
|
591
|
-
stmt.from(arel.
|
587
|
+
stmt.from(arel.source)
|
592
588
|
stmt.key = table[primary_key]
|
593
589
|
stmt.take(arel.limit)
|
594
590
|
stmt.offset(arel.offset)
|
595
591
|
stmt.order(*arel.orders)
|
596
592
|
stmt.wheres = arel.constraints
|
597
593
|
|
598
|
-
|
599
|
-
|
600
|
-
reset
|
601
|
-
affected
|
594
|
+
klass.connection.delete(stmt, "#{klass} Destroy").tap { reset }
|
602
595
|
end
|
603
596
|
|
604
597
|
# Finds and destroys all records matching the specified conditions.
|
@@ -652,6 +645,7 @@ module ActiveRecord
|
|
652
645
|
@delegate_to_klass = false
|
653
646
|
@to_sql = @arel = @loaded = @should_eager_load = nil
|
654
647
|
@offsets = @take = nil
|
648
|
+
@cache_keys = nil
|
655
649
|
@records = [].freeze
|
656
650
|
self
|
657
651
|
end
|
@@ -683,8 +677,7 @@ module ActiveRecord
|
|
683
677
|
end
|
684
678
|
|
685
679
|
def scope_for_create
|
686
|
-
hash =
|
687
|
-
hash.delete(klass.inheritance_column) if klass.finder_needs_type_condition?
|
680
|
+
hash = where_clause.to_h(klass.table_name, equality_only: true)
|
688
681
|
create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
|
689
682
|
hash
|
690
683
|
end
|
@@ -310,6 +310,7 @@ module ActiveRecord
|
|
310
310
|
type_cast_calculated_value(result.cast_values.first, operation) do |value|
|
311
311
|
type = column.try(:type_caster) ||
|
312
312
|
lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
|
313
|
+
type = type.subtype if Enum::EnumType === type
|
313
314
|
type.deserialize(value)
|
314
315
|
end
|
315
316
|
end
|
@@ -387,8 +388,11 @@ module ActiveRecord
|
|
387
388
|
key = key_records[key] if associated
|
388
389
|
|
389
390
|
result[key] = type_cast_calculated_value(row[column_alias], operation) do |value|
|
390
|
-
type
|
391
|
-
|
391
|
+
unless type
|
392
|
+
type = column.try(:type_caster) ||
|
393
|
+
lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
|
394
|
+
type = type.subtype if Enum::EnumType === type
|
395
|
+
end
|
392
396
|
type.deserialize(value)
|
393
397
|
end
|
394
398
|
end
|
@@ -326,7 +326,7 @@ module ActiveRecord
|
|
326
326
|
# compared to the records in memory. If the relation is unloaded, an
|
327
327
|
# efficient existence query is performed, as in #exists?.
|
328
328
|
def include?(record)
|
329
|
-
if loaded? || offset_value || limit_value
|
329
|
+
if loaded? || offset_value || limit_value || having_clause.any?
|
330
330
|
records.include?(record)
|
331
331
|
else
|
332
332
|
record.is_a?(klass) && exists?(record.id)
|
@@ -103,7 +103,9 @@ module ActiveRecord
|
|
103
103
|
|
104
104
|
klass ||= AssociationQueryValue
|
105
105
|
queries = klass.new(associated_table, value).queries.map! do |query|
|
106
|
-
|
106
|
+
# If the query produced is identical to attributes don't go any deeper.
|
107
|
+
# Prevents stack level too deep errors when association and foreign_key are identical.
|
108
|
+
query == attributes ? self[key, value] : expand_from_hash(query)
|
107
109
|
end
|
108
110
|
|
109
111
|
grouping_queries(queries)
|
@@ -1133,7 +1133,7 @@ module ActiveRecord
|
|
1133
1133
|
raise ImmutableRelation if defined?(@arel) && @arel
|
1134
1134
|
end
|
1135
1135
|
|
1136
|
-
def build_arel(aliases)
|
1136
|
+
def build_arel(aliases = nil)
|
1137
1137
|
arel = Arel::SelectManager.new(table)
|
1138
1138
|
|
1139
1139
|
build_joins(arel.join_sources, aliases)
|
@@ -58,8 +58,8 @@ module ActiveRecord
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
def to_h(table_name = nil)
|
62
|
-
equalities(predicates).each_with_object({}) do |node, hash|
|
61
|
+
def to_h(table_name = nil, equality_only: false)
|
62
|
+
equalities(predicates, equality_only).each_with_object({}) do |node, hash|
|
63
63
|
next if table_name&.!= node.left.relation.name
|
64
64
|
name = node.left.name.to_s
|
65
65
|
value = extract_node_value(node.right)
|
@@ -103,28 +103,31 @@ module ActiveRecord
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def extract_attributes
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end
|
110
|
-
attrs << attr if attr
|
111
|
-
end
|
106
|
+
attrs = []
|
107
|
+
each_attributes { |attr, _| attrs << attr }
|
108
|
+
attrs
|
112
109
|
end
|
113
110
|
|
114
111
|
protected
|
115
112
|
attr_reader :predicates
|
116
113
|
|
117
114
|
def referenced_columns
|
118
|
-
|
115
|
+
hash = {}
|
116
|
+
each_attributes { |attr, node| hash[attr] = node }
|
117
|
+
hash
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
def each_attributes
|
122
|
+
predicates.each do |node|
|
119
123
|
attr = extract_attribute(node) || begin
|
120
124
|
node.left if equality_node?(node) && node.left.is_a?(Arel::Predications)
|
121
125
|
end
|
122
126
|
|
123
|
-
|
127
|
+
yield attr, node if attr
|
124
128
|
end
|
125
129
|
end
|
126
130
|
|
127
|
-
private
|
128
131
|
def extract_attribute(node)
|
129
132
|
attr_node = nil
|
130
133
|
Arel.fetch_attribute(node) do |attr|
|
@@ -134,14 +137,14 @@ module ActiveRecord
|
|
134
137
|
attr_node
|
135
138
|
end
|
136
139
|
|
137
|
-
def equalities(predicates)
|
140
|
+
def equalities(predicates, equality_only)
|
138
141
|
equalities = []
|
139
142
|
|
140
143
|
predicates.each do |node|
|
141
|
-
if equality_node?(node)
|
144
|
+
if equality_only ? Arel::Nodes::Equality === node : equality_node?(node)
|
142
145
|
equalities << node
|
143
146
|
elsif node.is_a?(Arel::Nodes::And)
|
144
|
-
equalities.concat equalities(node.children)
|
147
|
+
equalities.concat equalities(node.children, equality_only)
|
145
148
|
end
|
146
149
|
end
|
147
150
|
|
@@ -109,9 +109,7 @@ module ActiveRecord
|
|
109
109
|
if default_scope_override
|
110
110
|
# The user has defined their own default scope method, so call that
|
111
111
|
evaluate_default_scope do
|
112
|
-
|
113
|
-
relation.merge!(scope)
|
114
|
-
end
|
112
|
+
relation.scoping { default_scope }
|
115
113
|
end
|
116
114
|
elsif default_scopes.any?
|
117
115
|
evaluate_default_scope do
|
@@ -80,8 +80,8 @@ module ActiveRecord
|
|
80
80
|
self
|
81
81
|
end
|
82
82
|
|
83
|
-
def add_binds(binds)
|
84
|
-
@binds.concat binds
|
83
|
+
def add_binds(binds, proc_for_binds = nil)
|
84
|
+
@binds.concat proc_for_binds ? binds.map(&proc_for_binds) : binds
|
85
85
|
binds.size.times do |i|
|
86
86
|
@parts << ", " unless i == 0
|
87
87
|
@parts << Substitute.new
|
@@ -111,6 +111,8 @@ module ActiveRecord
|
|
111
111
|
@fixture_connections = []
|
112
112
|
@@already_loaded_fixtures ||= {}
|
113
113
|
@connection_subscriber = nil
|
114
|
+
@legacy_saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
115
|
+
@saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
114
116
|
|
115
117
|
# Load fixtures once and begin transaction.
|
116
118
|
if run_in_transaction?
|
@@ -169,6 +171,7 @@ module ActiveRecord
|
|
169
171
|
connection.pool.lock_thread = false
|
170
172
|
end
|
171
173
|
@fixture_connections.clear
|
174
|
+
teardown_shared_connection_pool
|
172
175
|
else
|
173
176
|
ActiveRecord::FixtureSet.reset_cache
|
174
177
|
end
|
@@ -200,8 +203,13 @@ module ActiveRecord
|
|
200
203
|
return unless writing_pool_manager
|
201
204
|
|
202
205
|
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
206
|
+
@legacy_saved_pool_configs[handler][name] ||= {}
|
203
207
|
pool_manager.shard_names.each do |shard_name|
|
204
208
|
writing_pool_config = writing_pool_manager.get_pool_config(nil, shard_name)
|
209
|
+
pool_config = pool_manager.get_pool_config(nil, shard_name)
|
210
|
+
next if pool_config == writing_pool_config
|
211
|
+
|
212
|
+
@legacy_saved_pool_configs[handler][name][shard_name] = pool_config
|
205
213
|
pool_manager.set_pool_config(nil, shard_name, writing_pool_config)
|
206
214
|
end
|
207
215
|
end
|
@@ -214,8 +222,12 @@ module ActiveRecord
|
|
214
222
|
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
215
223
|
pool_manager.shard_names.each do |shard_name|
|
216
224
|
writing_pool_config = pool_manager.get_pool_config(ActiveRecord::Base.writing_role, shard_name)
|
225
|
+
@saved_pool_configs[name][shard_name] ||= {}
|
217
226
|
pool_manager.role_names.each do |role|
|
218
|
-
next unless pool_manager.get_pool_config(role, shard_name)
|
227
|
+
next unless pool_config = pool_manager.get_pool_config(role, shard_name)
|
228
|
+
next if pool_config == writing_pool_config
|
229
|
+
|
230
|
+
@saved_pool_configs[name][shard_name][role] = pool_config
|
219
231
|
pool_manager.set_pool_config(role, shard_name, writing_pool_config)
|
220
232
|
end
|
221
233
|
end
|
@@ -223,6 +235,35 @@ module ActiveRecord
|
|
223
235
|
end
|
224
236
|
end
|
225
237
|
|
238
|
+
def teardown_shared_connection_pool
|
239
|
+
if ActiveRecord::Base.legacy_connection_handling
|
240
|
+
@legacy_saved_pool_configs.each_pair do |handler, names|
|
241
|
+
names.each_pair do |name, shards|
|
242
|
+
shards.each_pair do |shard_name, pool_config|
|
243
|
+
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
244
|
+
pool_manager.set_pool_config(nil, shard_name, pool_config)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
else
|
249
|
+
handler = ActiveRecord::Base.connection_handler
|
250
|
+
|
251
|
+
@saved_pool_configs.each_pair do |name, shards|
|
252
|
+
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
253
|
+
shards.each_pair do |shard_name, roles|
|
254
|
+
roles.each_pair do |role, pool_config|
|
255
|
+
next unless pool_manager.get_pool_config(role, shard_name)
|
256
|
+
|
257
|
+
pool_manager.set_pool_config(role, shard_name, pool_config)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
@legacy_saved_pool_configs.clear
|
264
|
+
@saved_pool_configs.clear
|
265
|
+
end
|
266
|
+
|
226
267
|
def load_fixtures(config)
|
227
268
|
ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config).index_by(&:name)
|
228
269
|
end
|
@@ -4,7 +4,7 @@ module ActiveRecord
|
|
4
4
|
module Validations
|
5
5
|
class NumericalityValidator < ActiveModel::Validations::NumericalityValidator # :nodoc:
|
6
6
|
def validate_each(record, attribute, value, precision: nil, scale: nil)
|
7
|
-
precision = [column_precision_for(record, attribute) ||
|
7
|
+
precision = [column_precision_for(record, attribute) || Float::DIG, Float::DIG].min
|
8
8
|
scale = column_scale_for(record, attribute)
|
9
9
|
super(record, attribute, value, precision: precision, scale: scale)
|
10
10
|
end
|
data/lib/arel/collectors/bind.rb
CHANGED
@@ -22,9 +22,9 @@ module Arel # :nodoc: all
|
|
22
22
|
self
|
23
23
|
end
|
24
24
|
|
25
|
-
def add_binds(binds, &block)
|
26
|
-
left.add_binds(binds, &block)
|
27
|
-
right.add_binds(binds, &block)
|
25
|
+
def add_binds(binds, proc_for_binds = nil, &block)
|
26
|
+
left.add_binds(binds, proc_for_binds, &block)
|
27
|
+
right.add_binds(binds, proc_for_binds, &block)
|
28
28
|
self
|
29
29
|
end
|
30
30
|
|
data/lib/arel/predications.rb
CHANGED
@@ -207,11 +207,11 @@ module Arel # :nodoc: all
|
|
207
207
|
end
|
208
208
|
|
209
209
|
def contains(other)
|
210
|
-
Arel::Nodes::Contains.new
|
210
|
+
Arel::Nodes::Contains.new self, quoted_node(other)
|
211
211
|
end
|
212
212
|
|
213
213
|
def overlaps(other)
|
214
|
-
Arel::Nodes::Overlaps.new
|
214
|
+
Arel::Nodes::Overlaps.new self, quoted_node(other)
|
215
215
|
end
|
216
216
|
|
217
217
|
def quoted_array(others)
|
data/lib/arel/visitors/to_sql.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.1.
|
4
|
+
version: 6.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 6.1.
|
19
|
+
version: 6.1.4
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 6.1.
|
26
|
+
version: 6.1.4
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activemodel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 6.1.
|
33
|
+
version: 6.1.4
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 6.1.
|
40
|
+
version: 6.1.4
|
41
41
|
description: Databases on Rails. Build a persistent domain model by mapping database
|
42
42
|
tables to Ruby classes. Strong conventions for associations, validations, aggregations,
|
43
43
|
migrations, and testing come baked-in.
|
@@ -390,11 +390,11 @@ licenses:
|
|
390
390
|
- MIT
|
391
391
|
metadata:
|
392
392
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
393
|
-
changelog_uri: https://github.com/rails/rails/blob/v6.1.
|
394
|
-
documentation_uri: https://api.rubyonrails.org/v6.1.
|
393
|
+
changelog_uri: https://github.com/rails/rails/blob/v6.1.4/activerecord/CHANGELOG.md
|
394
|
+
documentation_uri: https://api.rubyonrails.org/v6.1.4/
|
395
395
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
396
|
-
source_code_uri: https://github.com/rails/rails/tree/v6.1.
|
397
|
-
post_install_message:
|
396
|
+
source_code_uri: https://github.com/rails/rails/tree/v6.1.4/activerecord
|
397
|
+
post_install_message:
|
398
398
|
rdoc_options:
|
399
399
|
- "--main"
|
400
400
|
- README.rdoc
|
@@ -411,8 +411,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
411
411
|
- !ruby/object:Gem::Version
|
412
412
|
version: '0'
|
413
413
|
requirements: []
|
414
|
-
rubygems_version: 3.2
|
415
|
-
signing_key:
|
414
|
+
rubygems_version: 3.1.2
|
415
|
+
signing_key:
|
416
416
|
specification_version: 4
|
417
417
|
summary: Object-relational mapper framework (part of Rails).
|
418
418
|
test_files: []
|