activerecord 6.1.0 → 6.1.6.1
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 +466 -26
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +4 -4
- data/lib/active_record/association_relation.rb +10 -0
- data/lib/active_record/associations/association.rb +13 -7
- data/lib/active_record/associations/association_scope.rb +7 -5
- data/lib/active_record/associations/belongs_to_association.rb +8 -5
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
- data/lib/active_record/associations/builder/association.rb +23 -2
- data/lib/active_record/associations/builder/belongs_to.rb +2 -2
- data/lib/active_record/associations/collection_association.rb +16 -8
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +8 -7
- data/lib/active_record/associations/join_dependency.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +1 -3
- data/lib/active_record/associations.rb +6 -2
- data/lib/active_record/attributes.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +13 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +5 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +7 -1
- data/lib/active_record/connection_adapters/abstract/transaction.rb +14 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +10 -11
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +6 -2
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +17 -2
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +4 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +4 -1
- data/lib/active_record/connection_adapters/pool_config.rb +13 -3
- data/lib/active_record/connection_adapters/pool_manager.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +2 -8
- data/lib/active_record/connection_adapters/schema_cache.rb +43 -11
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +0 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
- data/lib/active_record/connection_adapters.rb +2 -0
- data/lib/active_record/connection_handling.rb +22 -14
- data/lib/active_record/core.rb +68 -31
- data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -0
- data/lib/active_record/database_configurations/hash_config.rb +1 -1
- data/lib/active_record/database_configurations/url_config.rb +1 -1
- data/lib/active_record/database_configurations.rb +2 -1
- data/lib/active_record/enum.rb +52 -34
- data/lib/active_record/fixtures.rb +5 -2
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/insert_all.rb +5 -1
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +14 -4
- data/lib/active_record/log_subscriber.rb +3 -2
- data/lib/active_record/migration/compatibility.rb +9 -5
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/model_schema.rb +5 -5
- data/lib/active_record/railtie.rb +18 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/databases.rake +24 -17
- data/lib/active_record/reflection.rb +1 -1
- data/lib/active_record/relation/calculations.rb +8 -4
- data/lib/active_record/relation/finder_methods.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +3 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +9 -5
- data/lib/active_record/relation/predicate_builder.rb +5 -6
- data/lib/active_record/relation/query_methods.rb +11 -8
- data/lib/active_record/relation/where_clause.rb +19 -16
- data/lib/active_record/relation.rb +10 -17
- data/lib/active_record/scoping/default.rb +1 -3
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/statement_cache.rb +2 -2
- data/lib/active_record/table_metadata.rb +6 -3
- data/lib/active_record/tasks/database_tasks.rb +2 -1
- data/lib/active_record/test_fixtures.rb +42 -1
- data/lib/active_record/transactions.rb +4 -2
- data/lib/active_record/validations/numericality.rb +1 -1
- data/lib/active_record.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 +14 -13
@@ -167,6 +167,9 @@ module ActiveRecord
|
|
167
167
|
elsif type_metadata.extra == "DEFAULT_GENERATED"
|
168
168
|
default = +"(#{default})" unless default.start_with?("(")
|
169
169
|
default, default_function = nil, default
|
170
|
+
elsif type_metadata.type == :text && default
|
171
|
+
# strip and unescape quotes
|
172
|
+
default = default[1...-1].gsub("\\'", "'")
|
170
173
|
end
|
171
174
|
|
172
175
|
MySQL::Column.new(
|
@@ -203,7 +206,7 @@ module ActiveRecord
|
|
203
206
|
def data_source_sql(name = nil, type: nil)
|
204
207
|
scope = quoted_scope(name, type: type)
|
205
208
|
|
206
|
-
sql = +"SELECT table_name FROM (SELECT
|
209
|
+
sql = +"SELECT table_name FROM (SELECT table_name, table_type FROM information_schema.tables "
|
207
210
|
sql << " WHERE table_schema = #{scope[:schema]}) _subquery"
|
208
211
|
if scope[:type] || scope[:name]
|
209
212
|
conditions = []
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
class PoolConfig # :nodoc:
|
6
6
|
include Mutex_m
|
7
7
|
|
8
|
-
attr_reader :db_config, :
|
8
|
+
attr_reader :db_config, :connection_klass
|
9
9
|
attr_accessor :schema_cache
|
10
10
|
|
11
11
|
INSTANCES = ObjectSpace::WeakMap.new
|
@@ -17,14 +17,24 @@ module ActiveRecord
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def initialize(
|
20
|
+
def initialize(connection_klass, db_config)
|
21
21
|
super()
|
22
|
-
@
|
22
|
+
@connection_klass = connection_klass
|
23
23
|
@db_config = db_config
|
24
24
|
@pool = nil
|
25
25
|
INSTANCES[self] = self
|
26
26
|
end
|
27
27
|
|
28
|
+
def connection_specification_name
|
29
|
+
if connection_klass.is_a?(String)
|
30
|
+
connection_klass
|
31
|
+
elsif connection_klass.primary_class?
|
32
|
+
"ActiveRecord::Base"
|
33
|
+
else
|
34
|
+
connection_klass.name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
28
38
|
def disconnect!
|
29
39
|
ActiveSupport::ForkTracker.check!
|
30
40
|
|
@@ -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
|
@@ -28,6 +28,8 @@ module ActiveRecord
|
|
28
28
|
|
29
29
|
def write_query?(sql) # :nodoc:
|
30
30
|
!READ_QUERY.match?(sql)
|
31
|
+
rescue ArgumentError # Invalid encoding
|
32
|
+
!READ_QUERY.match?(sql.b)
|
31
33
|
end
|
32
34
|
|
33
35
|
# Executes an SQL statement, returning a PG::Result object on success
|
@@ -57,7 +59,7 @@ module ActiveRecord
|
|
57
59
|
ftype = result.ftype i
|
58
60
|
fmod = result.fmod i
|
59
61
|
case type = get_oid_type(ftype, fmod, fname)
|
60
|
-
when Type::Integer, Type::Float,
|
62
|
+
when Type::Integer, Type::Float, OID::Decimal, Type::String, Type::DateTime, Type::Boolean
|
61
63
|
# skip if a column has already been type casted by pg decoders
|
62
64
|
else types[fname] = type
|
63
65
|
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
|
|
@@ -227,11 +227,7 @@ module ActiveRecord
|
|
227
227
|
end
|
228
228
|
|
229
229
|
def next_key
|
230
|
-
"a#{@counter
|
231
|
-
end
|
232
|
-
|
233
|
-
def []=(sql, key)
|
234
|
-
super.tap { @counter += 1 }
|
230
|
+
"a#{@counter += 1}"
|
235
231
|
end
|
236
232
|
|
237
233
|
private
|
@@ -649,9 +645,7 @@ module ActiveRecord
|
|
649
645
|
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
650
646
|
end
|
651
647
|
|
652
|
-
if without_prepared_statement?(binds)
|
653
|
-
result = exec_no_cache(sql, name, [])
|
654
|
-
elsif !prepare
|
648
|
+
if !prepare || without_prepared_statement?(binds)
|
655
649
|
result = exec_no_cache(sql, name, binds)
|
656
650
|
else
|
657
651
|
result = exec_cache(sql, name, binds)
|
@@ -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
|
|
@@ -190,16 +198,40 @@ module ActiveRecord
|
|
190
198
|
@indexes = deep_deduplicate(@indexes)
|
191
199
|
end
|
192
200
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
201
|
+
if RUBY_VERSION < "2.7"
|
202
|
+
def deep_deduplicate(value)
|
203
|
+
case value
|
204
|
+
when Hash
|
205
|
+
value.transform_keys { |k| deep_deduplicate(k) }.transform_values { |v| deep_deduplicate(v) }
|
206
|
+
when Array
|
207
|
+
value.map { |i| deep_deduplicate(i) }
|
208
|
+
when String
|
209
|
+
if value.tainted?
|
210
|
+
# Ruby 2.6 and 2.7 have slightly different implementations of the String#-@ method.
|
211
|
+
# In Ruby 2.6, the receiver of the String#-@ method is modified under certain
|
212
|
+
# circumstances, and this was later identified as a bug
|
213
|
+
# (https://bugs.ruby-lang.org/issues/15926) and only fixed in Ruby 2.7.
|
214
|
+
value = value.dup
|
215
|
+
end
|
216
|
+
-value
|
217
|
+
when Deduplicable
|
218
|
+
-value
|
219
|
+
else
|
220
|
+
value
|
221
|
+
end
|
222
|
+
end
|
223
|
+
else
|
224
|
+
def deep_deduplicate(value)
|
225
|
+
case value
|
226
|
+
when Hash
|
227
|
+
value.transform_keys { |k| deep_deduplicate(k) }.transform_values { |v| deep_deduplicate(v) }
|
228
|
+
when Array
|
229
|
+
value.map { |i| deep_deduplicate(i) }
|
230
|
+
when String, Deduplicable
|
231
|
+
-value
|
232
|
+
else
|
233
|
+
value
|
234
|
+
end
|
203
235
|
end
|
204
236
|
end
|
205
237
|
|
@@ -271,7 +271,7 @@ module ActiveRecord
|
|
271
271
|
def change_column(table_name, column_name, type, **options) #:nodoc:
|
272
272
|
alter_table(table_name) do |definition|
|
273
273
|
definition[column_name].instance_eval do
|
274
|
-
self.type = type
|
274
|
+
self.type = aliased_types(type.to_s, type)
|
275
275
|
self.options.merge!(options)
|
276
276
|
end
|
277
277
|
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
|
@@ -91,6 +91,7 @@ module ActiveRecord
|
|
91
91
|
db_config, owner_name = resolve_config_for_connection(database_key)
|
92
92
|
handler = lookup_connection_handler(role.to_sym)
|
93
93
|
|
94
|
+
self.connection_class = true
|
94
95
|
connections << handler.establish_connection(db_config, owner_name: owner_name, role: role)
|
95
96
|
end
|
96
97
|
|
@@ -99,6 +100,7 @@ module ActiveRecord
|
|
99
100
|
db_config, owner_name = resolve_config_for_connection(database_key)
|
100
101
|
handler = lookup_connection_handler(role.to_sym)
|
101
102
|
|
103
|
+
self.connection_class = true
|
102
104
|
connections << handler.establish_connection(db_config, owner_name: owner_name, role: role, shard: shard.to_sym)
|
103
105
|
end
|
104
106
|
end
|
@@ -112,7 +114,7 @@ module ActiveRecord
|
|
112
114
|
#
|
113
115
|
# If only a role is passed, Active Record will look up the connection
|
114
116
|
# based on the requested role. If a non-established role is requested
|
115
|
-
# an
|
117
|
+
# an +ActiveRecord::ConnectionNotEstablished+ error will be raised:
|
116
118
|
#
|
117
119
|
# ActiveRecord::Base.connected_to(role: :writing) do
|
118
120
|
# Dog.create! # creates dog using dog writing connection
|
@@ -123,7 +125,7 @@ module ActiveRecord
|
|
123
125
|
# end
|
124
126
|
#
|
125
127
|
# When swapping to a shard, the role must be passed as well. If a non-existent
|
126
|
-
# shard is passed, an
|
128
|
+
# shard is passed, an +ActiveRecord::ConnectionNotEstablished+ error will be
|
127
129
|
# raised.
|
128
130
|
#
|
129
131
|
# When a shard and role is passed, Active Record will first lookup the role,
|
@@ -133,7 +135,7 @@ module ActiveRecord
|
|
133
135
|
# Dog.first # finds first Dog record stored on the shard one replica
|
134
136
|
# end
|
135
137
|
#
|
136
|
-
# The database kwarg is deprecated and will be removed in
|
138
|
+
# The database kwarg is deprecated and will be removed in Rails 7.0.0 without replacement.
|
137
139
|
def connected_to(database: nil, role: nil, shard: nil, prevent_writes: false, &blk)
|
138
140
|
if legacy_connection_handling
|
139
141
|
if self != Base
|
@@ -143,12 +145,16 @@ module ActiveRecord
|
|
143
145
|
if self != Base && !abstract_class
|
144
146
|
raise NotImplementedError, "calling `connected_to` is only allowed on ActiveRecord::Base or abstract classes."
|
145
147
|
end
|
148
|
+
|
149
|
+
if name != connection_specification_name && !primary_class?
|
150
|
+
raise NotImplementedError, "calling `connected_to` is only allowed on the abstract class that established the connection."
|
151
|
+
end
|
146
152
|
end
|
147
153
|
|
148
154
|
if database && (role || shard)
|
149
155
|
raise ArgumentError, "`connected_to` cannot accept a `database` argument with any other arguments."
|
150
156
|
elsif database
|
151
|
-
ActiveSupport::Deprecation.warn("The database key in `connected_to` is deprecated. It will be removed in Rails
|
157
|
+
ActiveSupport::Deprecation.warn("The database key in `connected_to` is deprecated. It will be removed in Rails 7.0.0 without replacement.")
|
152
158
|
|
153
159
|
if database.is_a?(Hash)
|
154
160
|
role, database = database.first
|
@@ -172,20 +178,22 @@ module ActiveRecord
|
|
172
178
|
end
|
173
179
|
end
|
174
180
|
|
175
|
-
# Connects a role and/or shard to the provided connection names. Optionally
|
176
|
-
# can be passed to block writes on a connection.
|
177
|
-
#
|
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.
|
178
184
|
#
|
179
|
-
#
|
185
|
+
# +connected_to_many+ is an alternative to deeply nested +connected_to+ blocks.
|
180
186
|
#
|
181
187
|
# Usage:
|
182
188
|
#
|
183
|
-
# ActiveRecord::Base.
|
189
|
+
# ActiveRecord::Base.connected_to_many(AnimalsRecord, MealsRecord, role: :reading) do
|
184
190
|
# Dog.first # Read from animals replica
|
185
191
|
# Dinner.first # Read from meals replica
|
186
192
|
# Person.first # Read from primary writer
|
187
193
|
# end
|
188
|
-
def connected_to_many(classes, role:, shard: nil, prevent_writes: false)
|
194
|
+
def connected_to_many(*classes, role:, shard: nil, prevent_writes: false)
|
195
|
+
classes = classes.flatten
|
196
|
+
|
189
197
|
if legacy_connection_handling
|
190
198
|
raise NotImplementedError, "connected_to_many is not available with legacy connection handling"
|
191
199
|
end
|
@@ -208,7 +216,7 @@ module ActiveRecord
|
|
208
216
|
# being used. For example, when booting a console in readonly mode.
|
209
217
|
#
|
210
218
|
# It is not recommended to use this method in a request since it
|
211
|
-
# does not yield to a block like
|
219
|
+
# does not yield to a block like +connected_to+.
|
212
220
|
def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
|
213
221
|
if legacy_connection_handling
|
214
222
|
raise NotImplementedError, "`connecting_to` is not available with `legacy_connection_handling`."
|
@@ -222,13 +230,13 @@ module ActiveRecord
|
|
222
230
|
# Prevent writing to the database regardless of role.
|
223
231
|
#
|
224
232
|
# In some cases you may want to prevent writes to the database
|
225
|
-
# even if you are on a database that can write.
|
233
|
+
# even if you are on a database that can write. +while_preventing_writes+
|
226
234
|
# will prevent writes to the database for the duration of the block.
|
227
235
|
#
|
228
236
|
# This method does not provide the same protection as a readonly
|
229
237
|
# user and is meant to be a safeguard against accidental writes.
|
230
238
|
#
|
231
|
-
# See
|
239
|
+
# See +READ_QUERY+ for the queries that are blocked by this
|
232
240
|
# method.
|
233
241
|
def while_preventing_writes(enabled = true, &block)
|
234
242
|
if legacy_connection_handling
|
@@ -357,7 +365,7 @@ module ActiveRecord
|
|
357
365
|
self.connection_specification_name = owner_name
|
358
366
|
|
359
367
|
db_config = Base.configurations.resolve(config_or_env)
|
360
|
-
[db_config,
|
368
|
+
[db_config, self]
|
361
369
|
end
|
362
370
|
|
363
371
|
def with_handler(handler_key, &blk)
|
data/lib/active_record/core.rb
CHANGED
@@ -155,6 +155,14 @@ module ActiveRecord
|
|
155
155
|
|
156
156
|
mattr_accessor :legacy_connection_handling, instance_writer: false, default: true
|
157
157
|
|
158
|
+
# Application configurable boolean that instructs the YAML Coder to use
|
159
|
+
# an unsafe load if set to true.
|
160
|
+
mattr_accessor :use_yaml_unsafe_load, instance_writer: false, default: false
|
161
|
+
|
162
|
+
# Application configurable array that provides additional permitted classes
|
163
|
+
# to Psych safe_load in the YAML Coder
|
164
|
+
mattr_accessor :yaml_column_permitted_classes, instance_writer: false, default: []
|
165
|
+
|
158
166
|
self.filter_attributes = []
|
159
167
|
|
160
168
|
def self.connection_handler
|
@@ -196,7 +204,7 @@ module ActiveRecord
|
|
196
204
|
else
|
197
205
|
connected_to_stack.reverse_each do |hash|
|
198
206
|
return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
|
199
|
-
return hash[:role] if hash[:role] && hash[:klasses].include?(
|
207
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(connection_classes)
|
200
208
|
end
|
201
209
|
|
202
210
|
default_role
|
@@ -215,7 +223,7 @@ module ActiveRecord
|
|
215
223
|
def self.current_shard
|
216
224
|
connected_to_stack.reverse_each do |hash|
|
217
225
|
return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
|
218
|
-
return hash[:shard] if hash[:shard] && hash[:klasses].include?(
|
226
|
+
return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_classes)
|
219
227
|
end
|
220
228
|
|
221
229
|
default_shard
|
@@ -237,7 +245,7 @@ module ActiveRecord
|
|
237
245
|
else
|
238
246
|
connected_to_stack.reverse_each do |hash|
|
239
247
|
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
|
240
|
-
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(
|
248
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_classes)
|
241
249
|
end
|
242
250
|
|
243
251
|
false
|
@@ -254,11 +262,23 @@ module ActiveRecord
|
|
254
262
|
end
|
255
263
|
end
|
256
264
|
|
257
|
-
def self.
|
265
|
+
def self.connection_class=(b) # :nodoc:
|
266
|
+
@connection_class = b
|
267
|
+
end
|
268
|
+
|
269
|
+
def self.connection_class # :nodoc
|
270
|
+
@connection_class ||= false
|
271
|
+
end
|
272
|
+
|
273
|
+
def self.connection_class? # :nodoc:
|
274
|
+
self.connection_class
|
275
|
+
end
|
276
|
+
|
277
|
+
def self.connection_classes # :nodoc:
|
258
278
|
klass = self
|
259
279
|
|
260
280
|
until klass == Base
|
261
|
-
break if klass.
|
281
|
+
break if klass.connection_class?
|
262
282
|
klass = klass.superclass
|
263
283
|
end
|
264
284
|
|
@@ -266,25 +286,25 @@ module ActiveRecord
|
|
266
286
|
end
|
267
287
|
|
268
288
|
def self.allow_unsafe_raw_sql # :nodoc:
|
269
|
-
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql is deprecated and will be removed in Rails
|
289
|
+
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql is deprecated and will be removed in Rails 7.0")
|
270
290
|
end
|
271
291
|
|
272
292
|
def self.allow_unsafe_raw_sql=(value) # :nodoc:
|
273
|
-
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql= is deprecated and will be removed in Rails
|
293
|
+
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql= is deprecated and will be removed in Rails 7.0")
|
274
294
|
end
|
275
295
|
|
276
296
|
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
277
297
|
self.default_role = writing_role
|
278
298
|
self.default_shard = :default
|
279
299
|
|
280
|
-
def self.strict_loading_violation!(owner:,
|
300
|
+
def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
|
281
301
|
case action_on_strict_loading_violation
|
282
302
|
when :raise
|
283
|
-
message = "`#{
|
303
|
+
message = "`#{owner}` is marked for strict_loading. The `#{reflection.klass}` association named `:#{reflection.name}` cannot be lazily loaded."
|
284
304
|
raise ActiveRecord::StrictLoadingViolationError.new(message)
|
285
305
|
when :log
|
286
306
|
name = "strict_loading_violation.active_record"
|
287
|
-
ActiveSupport::Notifications.instrument(name, owner: owner,
|
307
|
+
ActiveSupport::Notifications.instrument(name, owner: owner, reflection: reflection)
|
288
308
|
end
|
289
309
|
end
|
290
310
|
end
|
@@ -332,31 +352,37 @@ module ActiveRecord
|
|
332
352
|
hash = args.first
|
333
353
|
return super unless Hash === hash
|
334
354
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
355
|
+
hash = hash.each_with_object({}) do |(key, value), h|
|
356
|
+
key = key.to_s
|
357
|
+
key = attribute_aliases[key] || key
|
358
|
+
|
359
|
+
return super if reflect_on_aggregation(key)
|
360
|
+
|
361
|
+
reflection = _reflect_on_association(key)
|
362
|
+
|
363
|
+
if !reflection
|
364
|
+
value = value.id if value.respond_to?(:id)
|
365
|
+
elsif reflection.belongs_to? && !reflection.polymorphic?
|
366
|
+
key = reflection.join_foreign_key
|
367
|
+
pkey = reflection.join_primary_key
|
368
|
+
value = value.public_send(pkey) if value.respond_to?(pkey)
|
369
|
+
end
|
370
|
+
|
371
|
+
if !columns_hash.key?(key) || StatementCache.unsupported_value?(value)
|
372
|
+
return super
|
348
373
|
end
|
349
|
-
end
|
350
374
|
|
351
|
-
|
375
|
+
h[key] = value
|
376
|
+
end
|
352
377
|
|
378
|
+
keys = hash.keys
|
353
379
|
statement = cached_find_by_statement(keys) { |params|
|
354
380
|
wheres = keys.index_with { params.bind }
|
355
381
|
where(wheres).limit(1)
|
356
382
|
}
|
357
383
|
|
358
384
|
begin
|
359
|
-
statement.execute(values, connection).first
|
385
|
+
statement.execute(hash.values, connection).first
|
360
386
|
rescue TypeError
|
361
387
|
raise ActiveRecord::StatementInvalid
|
362
388
|
end
|
@@ -390,7 +416,21 @@ module ActiveRecord
|
|
390
416
|
end
|
391
417
|
|
392
418
|
# Specifies columns which shouldn't be exposed while calling +#inspect+.
|
393
|
-
|
419
|
+
def filter_attributes=(filter_attributes)
|
420
|
+
@inspection_filter = nil
|
421
|
+
@filter_attributes = filter_attributes
|
422
|
+
end
|
423
|
+
|
424
|
+
def inspection_filter # :nodoc:
|
425
|
+
if defined?(@filter_attributes)
|
426
|
+
@inspection_filter ||= begin
|
427
|
+
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
428
|
+
ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
|
429
|
+
end
|
430
|
+
else
|
431
|
+
superclass.inspection_filter
|
432
|
+
end
|
433
|
+
end
|
394
434
|
|
395
435
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
396
436
|
def inspect # :nodoc:
|
@@ -758,10 +798,7 @@ module ActiveRecord
|
|
758
798
|
private_constant :InspectionMask
|
759
799
|
|
760
800
|
def inspection_filter
|
761
|
-
|
762
|
-
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
763
|
-
ActiveSupport::ParameterFilter.new(self.class.filter_attributes, mask: mask)
|
764
|
-
end
|
801
|
+
self.class.inspection_filter
|
765
802
|
end
|
766
803
|
end
|
767
804
|
end
|
@@ -32,7 +32,7 @@ module ActiveRecord
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def config
|
35
|
-
ActiveSupport::Deprecation.warn("DatabaseConfig#config will be removed in
|
35
|
+
ActiveSupport::Deprecation.warn("DatabaseConfig#config will be removed in 7.0.0 in favor of DatabaseConfig#configuration_hash which returns a hash with symbol keys")
|
36
36
|
configuration_hash.stringify_keys
|
37
37
|
end
|
38
38
|
|
@@ -42,7 +42,7 @@ module ActiveRecord
|
|
42
42
|
# Return a Hash that can be merged into the main config that represents
|
43
43
|
# the passed in url
|
44
44
|
def build_url_hash
|
45
|
-
if url.nil? || url.start_with?(
|
45
|
+
if url.nil? || %w(jdbc: http: https:).any? { |protocol| url.start_with?(protocol) }
|
46
46
|
{ url: url }
|
47
47
|
else
|
48
48
|
ConnectionUrlResolver.new(url).to_hash
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "uri"
|
3
4
|
require "active_record/database_configurations/database_config"
|
4
5
|
require "active_record/database_configurations/hash_config"
|
5
6
|
require "active_record/database_configurations/url_config"
|
@@ -40,7 +41,7 @@ module ActiveRecord
|
|
40
41
|
def configs_for(env_name: nil, spec_name: nil, name: nil, include_replicas: false)
|
41
42
|
if spec_name
|
42
43
|
name = spec_name
|
43
|
-
ActiveSupport::Deprecation.warn("The kwarg `spec_name` is deprecated in favor of `name`. `spec_name` will be removed in Rails
|
44
|
+
ActiveSupport::Deprecation.warn("The kwarg `spec_name` is deprecated in favor of `name`. `spec_name` will be removed in Rails 7.0")
|
44
45
|
end
|
45
46
|
|
46
47
|
env_name ||= default_env if name
|