activerecord 7.2.2 → 8.0.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.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +239 -878
- data/README.rdoc +1 -1
- data/lib/active_record/association_relation.rb +1 -0
- data/lib/active_record/associations/association.rb +34 -10
- data/lib/active_record/associations/builder/association.rb +7 -6
- data/lib/active_record/associations/collection_association.rb +10 -8
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +34 -4
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +2 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -12
- data/lib/active_record/attribute_methods.rb +1 -1
- data/lib/active_record/autosave_association.rb +69 -27
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +16 -10
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +0 -9
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +33 -6
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +21 -39
- data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -45
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +42 -98
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -8
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -11
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +6 -12
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +59 -16
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +45 -95
- data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -12
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +0 -17
- data/lib/active_record/connection_adapters.rb +0 -56
- data/lib/active_record/connection_handling.rb +22 -0
- data/lib/active_record/core.rb +18 -14
- data/lib/active_record/database_configurations/database_config.rb +4 -0
- data/lib/active_record/database_configurations/hash_config.rb +8 -0
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +4 -4
- data/lib/active_record/encryption/encrypted_attribute_type.rb +10 -1
- data/lib/active_record/encryption/encryptor.rb +15 -8
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +8 -1
- data/lib/active_record/enum.rb +9 -22
- data/lib/active_record/errors.rb +13 -5
- data/lib/active_record/fixtures.rb +0 -2
- data/lib/active_record/future_result.rb +14 -10
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/insert_all.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +5 -11
- data/lib/active_record/migration/command_recorder.rb +27 -10
- data/lib/active_record/migration/compatibility.rb +5 -2
- data/lib/active_record/migration.rb +35 -38
- data/lib/active_record/model_schema.rb +3 -4
- data/lib/active_record/nested_attributes.rb +4 -6
- data/lib/active_record/persistence.rb +128 -130
- data/lib/active_record/query_logs.rb +102 -50
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +8 -8
- data/lib/active_record/railtie.rb +2 -26
- data/lib/active_record/railties/databases.rake +2 -17
- data/lib/active_record/reflection.rb +18 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +132 -72
- data/lib/active_record/relation/calculations.rb +40 -39
- data/lib/active_record/relation/delegation.rb +25 -14
- data/lib/active_record/relation/finder_methods.rb +18 -18
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +13 -0
- data/lib/active_record/relation/query_methods.rb +115 -65
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation.rb +79 -61
- data/lib/active_record/result.rb +66 -4
- data/lib/active_record/sanitization.rb +7 -6
- data/lib/active_record/schema_dumper.rb +5 -0
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/statement_cache.rb +12 -12
- data/lib/active_record/store.rb +7 -3
- data/lib/active_record/table_metadata.rb +1 -3
- data/lib/active_record/tasks/database_tasks.rb +48 -47
- data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
- data/lib/active_record/test_fixtures.rb +12 -0
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +15 -45
- data/lib/arel/collectors/bind.rb +1 -1
- data/lib/arel/table.rb +3 -7
- metadata +11 -12
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
data/lib/active_record/core.rb
CHANGED
|
@@ -89,6 +89,7 @@ module ActiveRecord
|
|
|
89
89
|
class_attribute :belongs_to_required_by_default, instance_accessor: false
|
|
90
90
|
|
|
91
91
|
class_attribute :strict_loading_by_default, instance_accessor: false, default: false
|
|
92
|
+
class_attribute :strict_loading_mode, instance_accessor: false, default: :all
|
|
92
93
|
|
|
93
94
|
class_attribute :has_many_inversing, instance_accessor: false, default: false
|
|
94
95
|
|
|
@@ -381,7 +382,7 @@ module ActiveRecord
|
|
|
381
382
|
end
|
|
382
383
|
|
|
383
384
|
def predicate_builder # :nodoc:
|
|
384
|
-
@predicate_builder ||= PredicateBuilder.new(
|
|
385
|
+
@predicate_builder ||= PredicateBuilder.new(TableMetadata.new(self, arel_table))
|
|
385
386
|
end
|
|
386
387
|
|
|
387
388
|
def type_caster # :nodoc:
|
|
@@ -426,10 +427,6 @@ module ActiveRecord
|
|
|
426
427
|
end
|
|
427
428
|
end
|
|
428
429
|
|
|
429
|
-
def table_metadata
|
|
430
|
-
TableMetadata.new(self, arel_table)
|
|
431
|
-
end
|
|
432
|
-
|
|
433
430
|
def cached_find_by(keys, values)
|
|
434
431
|
with_connection do |connection|
|
|
435
432
|
statement = cached_find_by_statement(connection, keys) { |params|
|
|
@@ -443,8 +440,8 @@ module ActiveRecord
|
|
|
443
440
|
where(wheres).limit(1)
|
|
444
441
|
}
|
|
445
442
|
|
|
446
|
-
|
|
447
|
-
|
|
443
|
+
statement.execute(values.flatten, connection, allow_retry: true).then do |r|
|
|
444
|
+
r.first
|
|
448
445
|
rescue TypeError
|
|
449
446
|
raise ActiveRecord::StatementInvalid
|
|
450
447
|
end
|
|
@@ -540,12 +537,7 @@ module ActiveRecord
|
|
|
540
537
|
|
|
541
538
|
##
|
|
542
539
|
def initialize_dup(other) # :nodoc:
|
|
543
|
-
@attributes =
|
|
544
|
-
if self.class.composite_primary_key?
|
|
545
|
-
@primary_key.each { |key| @attributes.reset(key) }
|
|
546
|
-
else
|
|
547
|
-
@attributes.reset(@primary_key)
|
|
548
|
-
end
|
|
540
|
+
@attributes = init_attributes(other)
|
|
549
541
|
|
|
550
542
|
_run_initialize_callbacks
|
|
551
543
|
|
|
@@ -557,6 +549,18 @@ module ActiveRecord
|
|
|
557
549
|
super
|
|
558
550
|
end
|
|
559
551
|
|
|
552
|
+
def init_attributes(_) # :nodoc:
|
|
553
|
+
attrs = @attributes.deep_dup
|
|
554
|
+
|
|
555
|
+
if self.class.composite_primary_key?
|
|
556
|
+
@primary_key.each { |key| attrs.reset(key) }
|
|
557
|
+
else
|
|
558
|
+
attrs.reset(@primary_key)
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
attrs
|
|
562
|
+
end
|
|
563
|
+
|
|
560
564
|
# Populate +coder+ with attributes about this record that should be
|
|
561
565
|
# serialized. The structure of +coder+ defined in this method is
|
|
562
566
|
# guaranteed to match the structure of +coder+ passed to the #init_with
|
|
@@ -810,7 +814,7 @@ module ActiveRecord
|
|
|
810
814
|
|
|
811
815
|
@primary_key = klass.primary_key
|
|
812
816
|
@strict_loading = klass.strict_loading_by_default
|
|
813
|
-
@strict_loading_mode =
|
|
817
|
+
@strict_loading_mode = klass.strict_loading_mode
|
|
814
818
|
|
|
815
819
|
klass.define_attribute_methods
|
|
816
820
|
end
|
|
@@ -130,6 +130,14 @@ module ActiveRecord
|
|
|
130
130
|
Base.configurations.primary?(name)
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
+
# Determines whether the db:prepare task should seed the database from db/seeds.rb.
|
|
134
|
+
#
|
|
135
|
+
# If the `seeds` key is present in the config, `seeds?` will return its value. Otherwise, it
|
|
136
|
+
# will return `true` for the primary database and `false` for all other configs.
|
|
137
|
+
def seeds?
|
|
138
|
+
configuration_hash.fetch(:seeds, primary?)
|
|
139
|
+
end
|
|
140
|
+
|
|
133
141
|
# Determines whether to dump the schema/structure files and the filename that
|
|
134
142
|
# should be used.
|
|
135
143
|
#
|
|
@@ -8,7 +8,8 @@ module ActiveRecord
|
|
|
8
8
|
class Config
|
|
9
9
|
attr_accessor :primary_key, :deterministic_key, :store_key_references, :key_derivation_salt, :hash_digest_class,
|
|
10
10
|
:support_unencrypted_data, :encrypt_fixtures, :validate_column_size, :add_to_filter_parameters,
|
|
11
|
-
:excluded_from_filter_parameters, :extend_queries, :previous_schemes, :forced_encoding_for_deterministic_encryption
|
|
11
|
+
:excluded_from_filter_parameters, :extend_queries, :previous_schemes, :forced_encoding_for_deterministic_encryption,
|
|
12
|
+
:compressor
|
|
12
13
|
|
|
13
14
|
def initialize
|
|
14
15
|
set_defaults
|
|
@@ -55,6 +56,7 @@ module ActiveRecord
|
|
|
55
56
|
self.previous_schemes = []
|
|
56
57
|
self.forced_encoding_for_deterministic_encryption = Encoding::UTF_8
|
|
57
58
|
self.hash_digest_class = OpenSSL::Digest::SHA1
|
|
59
|
+
self.compressor = Zlib
|
|
58
60
|
|
|
59
61
|
# TODO: Setting to false for now as the implementation is a bit experimental
|
|
60
62
|
self.extend_queries = false
|
|
@@ -46,11 +46,11 @@ module ActiveRecord
|
|
|
46
46
|
# * <tt>:previous</tt> - List of previous encryption schemes. When provided, they will be used in order when trying to read
|
|
47
47
|
# the attribute. Each entry of the list can contain the properties supported by #encrypts. Also, when deterministic
|
|
48
48
|
# encryption is used, they will be used to generate additional ciphertexts to check in the queries.
|
|
49
|
-
def encrypts(*names, key_provider: nil, key: nil, deterministic: false, support_unencrypted_data: nil, downcase: false, ignore_case: false, previous: [], **context_properties)
|
|
49
|
+
def encrypts(*names, key_provider: nil, key: nil, deterministic: false, support_unencrypted_data: nil, downcase: false, ignore_case: false, previous: [], compress: true, compressor: nil, **context_properties)
|
|
50
50
|
self.encrypted_attributes ||= Set.new # not using :default because the instance would be shared across classes
|
|
51
51
|
|
|
52
52
|
names.each do |name|
|
|
53
|
-
encrypt_attribute name, key_provider: key_provider, key: key, deterministic: deterministic, support_unencrypted_data: support_unencrypted_data, downcase: downcase, ignore_case: ignore_case, previous: previous, **context_properties
|
|
53
|
+
encrypt_attribute name, key_provider: key_provider, key: key, deterministic: deterministic, support_unencrypted_data: support_unencrypted_data, downcase: downcase, ignore_case: ignore_case, previous: previous, compress: compress, compressor: compressor, **context_properties
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
|
|
@@ -81,12 +81,12 @@ module ActiveRecord
|
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
def encrypt_attribute(name, key_provider: nil, key: nil, deterministic: false, support_unencrypted_data: nil, downcase: false, ignore_case: false, previous: [], **context_properties)
|
|
84
|
+
def encrypt_attribute(name, key_provider: nil, key: nil, deterministic: false, support_unencrypted_data: nil, downcase: false, ignore_case: false, previous: [], compress: true, compressor: nil, **context_properties)
|
|
85
85
|
encrypted_attributes << name.to_sym
|
|
86
86
|
|
|
87
87
|
decorate_attributes([name]) do |name, cast_type|
|
|
88
88
|
scheme = scheme_for key_provider: key_provider, key: key, deterministic: deterministic, support_unencrypted_data: support_unencrypted_data, \
|
|
89
|
-
downcase: downcase, ignore_case: ignore_case, previous: previous, **context_properties
|
|
89
|
+
downcase: downcase, ignore_case: ignore_case, previous: previous, compress: compress, compressor: compressor, **context_properties
|
|
90
90
|
|
|
91
91
|
ActiveRecord::Encryption::EncryptedAttributeType.new(scheme: scheme, cast_type: cast_type, default: columns_hash[name.to_s]&.default)
|
|
92
92
|
end
|
|
@@ -100,7 +100,7 @@ module ActiveRecord
|
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
def decrypt(value)
|
|
103
|
-
text_to_database_type decrypt_as_text(value)
|
|
103
|
+
text_to_database_type decrypt_as_text(database_type_to_text(value))
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def try_to_deserialize_with_previous_encrypted_types(value)
|
|
@@ -170,6 +170,15 @@ module ActiveRecord
|
|
|
170
170
|
value
|
|
171
171
|
end
|
|
172
172
|
end
|
|
173
|
+
|
|
174
|
+
def database_type_to_text(value)
|
|
175
|
+
if value && cast_type.binary?
|
|
176
|
+
binary_cast_type = cast_type.serialized? ? cast_type.subtype : cast_type
|
|
177
|
+
binary_cast_type.deserialize(value)
|
|
178
|
+
else
|
|
179
|
+
value
|
|
180
|
+
end
|
|
181
|
+
end
|
|
173
182
|
end
|
|
174
183
|
end
|
|
175
184
|
end
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "openssl"
|
|
4
|
-
require "zlib"
|
|
5
4
|
require "active_support/core_ext/numeric"
|
|
6
5
|
|
|
7
6
|
module ActiveRecord
|
|
@@ -12,12 +11,20 @@ module ActiveRecord
|
|
|
12
11
|
# It interacts with a KeyProvider for getting the keys, and delegate to
|
|
13
12
|
# ActiveRecord::Encryption::Cipher the actual encryption algorithm.
|
|
14
13
|
class Encryptor
|
|
14
|
+
# The compressor to use for compressing the payload
|
|
15
|
+
attr_reader :compressor
|
|
16
|
+
|
|
15
17
|
# === Options
|
|
16
18
|
#
|
|
17
19
|
# * <tt>:compress</tt> - Boolean indicating whether records should be compressed before encryption.
|
|
18
20
|
# Defaults to +true+.
|
|
19
|
-
|
|
21
|
+
# * <tt>:compressor</tt> - The compressor to use.
|
|
22
|
+
# 1. If compressor is provided, it will be used.
|
|
23
|
+
# 2. If not, it will use ActiveRecord::Encryption.config.compressor which default value is +Zlib+.
|
|
24
|
+
# If you want to use a custom compressor, it must respond to +deflate+ and +inflate+.
|
|
25
|
+
def initialize(compress: true, compressor: nil)
|
|
20
26
|
@compress = compress
|
|
27
|
+
@compressor = compressor || ActiveRecord::Encryption.config.compressor
|
|
21
28
|
end
|
|
22
29
|
|
|
23
30
|
# Encrypts +clean_text+ and returns the encrypted result
|
|
@@ -78,6 +85,10 @@ module ActiveRecord
|
|
|
78
85
|
serializer.binary?
|
|
79
86
|
end
|
|
80
87
|
|
|
88
|
+
def compress? # :nodoc:
|
|
89
|
+
@compress
|
|
90
|
+
end
|
|
91
|
+
|
|
81
92
|
private
|
|
82
93
|
DECRYPT_ERRORS = [OpenSSL::Cipher::CipherError, Errors::EncryptedContentIntegrity, Errors::Decryption]
|
|
83
94
|
ENCODING_ERRORS = [EncodingError, Errors::Encoding]
|
|
@@ -130,12 +141,8 @@ module ActiveRecord
|
|
|
130
141
|
end
|
|
131
142
|
end
|
|
132
143
|
|
|
133
|
-
def compress?
|
|
134
|
-
@compress
|
|
135
|
-
end
|
|
136
|
-
|
|
137
144
|
def compress(data)
|
|
138
|
-
|
|
145
|
+
@compressor.deflate(data).tap do |compressed_data|
|
|
139
146
|
compressed_data.force_encoding(data.encoding)
|
|
140
147
|
end
|
|
141
148
|
end
|
|
@@ -149,7 +156,7 @@ module ActiveRecord
|
|
|
149
156
|
end
|
|
150
157
|
|
|
151
158
|
def uncompress(data)
|
|
152
|
-
|
|
159
|
+
@compressor.inflate(data).tap do |uncompressed_data|
|
|
153
160
|
uncompressed_data.force_encoding(data.encoding)
|
|
154
161
|
end
|
|
155
162
|
end
|
|
@@ -41,6 +41,8 @@ module ActiveRecord
|
|
|
41
41
|
module EncryptedQuery # :nodoc:
|
|
42
42
|
class << self
|
|
43
43
|
def process_arguments(owner, args, check_for_additional_values)
|
|
44
|
+
owner = owner.model if owner.is_a?(Relation)
|
|
45
|
+
|
|
44
46
|
return args if owner.deterministic_encrypted_attributes&.empty?
|
|
45
47
|
|
|
46
48
|
if args.is_a?(Array) && (options = args.first).is_a?(Hash)
|
|
@@ -102,12 +104,12 @@ module ActiveRecord
|
|
|
102
104
|
end
|
|
103
105
|
|
|
104
106
|
def scope_for_create
|
|
105
|
-
return super unless
|
|
107
|
+
return super unless model.deterministic_encrypted_attributes&.any?
|
|
106
108
|
|
|
107
109
|
scope_attributes = super
|
|
108
110
|
wheres = where_values_hash
|
|
109
111
|
|
|
110
|
-
|
|
112
|
+
model.deterministic_encrypted_attributes.each do |attribute_name|
|
|
111
113
|
attribute_name = attribute_name.to_s
|
|
112
114
|
values = wheres[attribute_name]
|
|
113
115
|
if values.is_a?(Array) && values[1..].all?(AdditionalValue)
|
|
@@ -11,7 +11,7 @@ module ActiveRecord
|
|
|
11
11
|
attr_accessor :previous_schemes
|
|
12
12
|
|
|
13
13
|
def initialize(key_provider: nil, key: nil, deterministic: nil, support_unencrypted_data: nil, downcase: nil, ignore_case: nil,
|
|
14
|
-
previous_schemes: nil, **context_properties)
|
|
14
|
+
previous_schemes: nil, compress: true, compressor: nil, **context_properties)
|
|
15
15
|
# Initializing all attributes to +nil+ as we want to allow a "not set" semantics so that we
|
|
16
16
|
# can merge schemes without overriding values with defaults. See +#merge+
|
|
17
17
|
|
|
@@ -24,8 +24,13 @@ module ActiveRecord
|
|
|
24
24
|
@previous_schemes_param = previous_schemes
|
|
25
25
|
@previous_schemes = Array.wrap(previous_schemes)
|
|
26
26
|
@context_properties = context_properties
|
|
27
|
+
@compress = compress
|
|
28
|
+
@compressor = compressor
|
|
27
29
|
|
|
28
30
|
validate_config!
|
|
31
|
+
|
|
32
|
+
@context_properties[:encryptor] = Encryptor.new(compress: @compress) unless @compress
|
|
33
|
+
@context_properties[:encryptor] = Encryptor.new(compressor: compressor) if compressor
|
|
29
34
|
end
|
|
30
35
|
|
|
31
36
|
def ignore_case?
|
|
@@ -78,6 +83,8 @@ module ActiveRecord
|
|
|
78
83
|
def validate_config!
|
|
79
84
|
raise Errors::Configuration, "ignore_case: can only be used with deterministic encryption" if @ignore_case && !@deterministic
|
|
80
85
|
raise Errors::Configuration, "key_provider: and key: can't be used simultaneously" if @key_provider_param && @key
|
|
86
|
+
raise Errors::Configuration, "compressor: can't be used with compress: false" if !@compress && @compressor
|
|
87
|
+
raise Errors::Configuration, "compressor: can't be used with encryptor" if @compressor && @context_properties[:encryptor]
|
|
81
88
|
end
|
|
82
89
|
|
|
83
90
|
def key_provider_from_key
|
data/lib/active_record/enum.rb
CHANGED
|
@@ -213,34 +213,16 @@ module ActiveRecord
|
|
|
213
213
|
attr_reader :name, :mapping
|
|
214
214
|
end
|
|
215
215
|
|
|
216
|
-
def enum(name
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
return _enum(name, values, **options)
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default, :_instance_methods)
|
|
223
|
-
options.transform_keys! { |key| :"#{key[1..-1]}" }
|
|
224
|
-
|
|
225
|
-
definitions.each { |name, values| _enum(name, values, **options) }
|
|
226
|
-
|
|
227
|
-
ActiveRecord.deprecator.warn(<<~MSG)
|
|
228
|
-
Defining enums with keyword arguments is deprecated and will be removed
|
|
229
|
-
in Rails 8.0. Positional arguments should be used instead:
|
|
230
|
-
|
|
231
|
-
#{definitions.map { |name, values| "enum :#{name}, #{values}" }.join("\n")}
|
|
232
|
-
MSG
|
|
216
|
+
def enum(name, values = nil, **options)
|
|
217
|
+
values, options = options, {} unless values
|
|
218
|
+
_enum(name, values, **options)
|
|
233
219
|
end
|
|
234
220
|
|
|
235
221
|
private
|
|
236
|
-
def inherited(base)
|
|
237
|
-
base.defined_enums = defined_enums.deep_dup
|
|
238
|
-
super
|
|
239
|
-
end
|
|
240
|
-
|
|
241
222
|
def _enum(name, values, prefix: nil, suffix: nil, scopes: true, instance_methods: true, validate: false, **options)
|
|
242
223
|
assert_valid_enum_definition_values(values)
|
|
243
224
|
assert_valid_enum_options(options)
|
|
225
|
+
|
|
244
226
|
# statuses = { }
|
|
245
227
|
enum_values = ActiveSupport::HashWithIndifferentAccess.new
|
|
246
228
|
name = name.to_s
|
|
@@ -304,6 +286,11 @@ module ActiveRecord
|
|
|
304
286
|
enum_values.freeze
|
|
305
287
|
end
|
|
306
288
|
|
|
289
|
+
def inherited(base)
|
|
290
|
+
base.defined_enums = defined_enums.deep_dup
|
|
291
|
+
super
|
|
292
|
+
end
|
|
293
|
+
|
|
307
294
|
class EnumMethods < Module # :nodoc:
|
|
308
295
|
def initialize(klass)
|
|
309
296
|
@klass = klass
|
data/lib/active_record/errors.rb
CHANGED
|
@@ -84,6 +84,19 @@ module ActiveRecord
|
|
|
84
84
|
class ConnectionTimeoutError < ConnectionNotEstablished
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
# Raised when a database connection pool is requested but
|
|
88
|
+
# has not been defined.
|
|
89
|
+
class ConnectionNotDefined < ConnectionNotEstablished
|
|
90
|
+
def initialize(message = nil, connection_name: nil, role: nil, shard: nil)
|
|
91
|
+
super(message)
|
|
92
|
+
@connection_name = connection_name
|
|
93
|
+
@role = role
|
|
94
|
+
@shard = shard
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
attr_reader :connection_name, :role, :shard
|
|
98
|
+
end
|
|
99
|
+
|
|
87
100
|
# Raised when connection to the database could not been established because it was not
|
|
88
101
|
# able to connect to the host or when the authorization failed.
|
|
89
102
|
class DatabaseConnectionError < ConnectionNotEstablished
|
|
@@ -484,11 +497,6 @@ module ActiveRecord
|
|
|
484
497
|
# relation.limit!(5) # => ActiveRecord::UnmodifiableRelation
|
|
485
498
|
class UnmodifiableRelation < ActiveRecordError
|
|
486
499
|
end
|
|
487
|
-
deprecate_constant(
|
|
488
|
-
:ImmutableRelation,
|
|
489
|
-
"ActiveRecord::UnmodifiableRelation",
|
|
490
|
-
deprecator: ActiveRecord.deprecator
|
|
491
|
-
)
|
|
492
500
|
|
|
493
501
|
# TransactionIsolationError will be raised under the following conditions:
|
|
494
502
|
#
|
|
@@ -100,17 +100,21 @@ module ActiveRecord
|
|
|
100
100
|
def execute_or_skip
|
|
101
101
|
return unless pending?
|
|
102
102
|
|
|
103
|
-
@
|
|
104
|
-
return unless
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
@session.synchronize do
|
|
104
|
+
return unless pending?
|
|
105
|
+
|
|
106
|
+
@pool.with_connection do |connection|
|
|
107
|
+
return unless @mutex.try_lock
|
|
108
|
+
begin
|
|
109
|
+
if pending?
|
|
110
|
+
@event_buffer = EventBuffer.new(self, @instrumenter)
|
|
111
|
+
connection.with_instrumenter(@event_buffer) do
|
|
112
|
+
execute_query(connection, async: true)
|
|
113
|
+
end
|
|
110
114
|
end
|
|
115
|
+
ensure
|
|
116
|
+
@mutex.unlock
|
|
111
117
|
end
|
|
112
|
-
ensure
|
|
113
|
-
@mutex.unlock
|
|
114
118
|
end
|
|
115
119
|
end
|
|
116
120
|
end
|
|
@@ -163,7 +167,7 @@ module ActiveRecord
|
|
|
163
167
|
end
|
|
164
168
|
|
|
165
169
|
def exec_query(connection, *args, **kwargs)
|
|
166
|
-
connection.
|
|
170
|
+
connection.raw_exec_query(*args, **kwargs)
|
|
167
171
|
end
|
|
168
172
|
|
|
169
173
|
class SelectAll < FutureResult # :nodoc:
|
|
@@ -240,7 +240,7 @@ module ActiveRecord
|
|
|
240
240
|
|
|
241
241
|
values_list = insert_all.map_key_with_value do |key, value|
|
|
242
242
|
next value if Arel::Nodes::SqlLiteral === value
|
|
243
|
-
|
|
243
|
+
ActiveModel::Type::SerializeCastValue.serialize(type = types[key], type.cast(value))
|
|
244
244
|
end
|
|
245
245
|
|
|
246
246
|
connection.visitor.compile(Arel::Nodes::ValuesList.new(values_list))
|
|
@@ -9,7 +9,7 @@ module ActiveRecord
|
|
|
9
9
|
# it was opened, an ActiveRecord::StaleObjectError exception is thrown if that has occurred
|
|
10
10
|
# and the update is ignored.
|
|
11
11
|
#
|
|
12
|
-
# Check out
|
|
12
|
+
# Check out ActiveRecord::Locking::Pessimistic for an alternative.
|
|
13
13
|
#
|
|
14
14
|
# == Usage
|
|
15
15
|
#
|
|
@@ -126,18 +126,12 @@ module ActiveRecord
|
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return frame if frame
|
|
134
|
-
end
|
|
135
|
-
nil
|
|
136
|
-
end
|
|
137
|
-
else
|
|
138
|
-
def query_source_location
|
|
139
|
-
backtrace_cleaner.clean(caller(1).lazy).first
|
|
129
|
+
def query_source_location
|
|
130
|
+
Thread.each_caller_location do |location|
|
|
131
|
+
frame = backtrace_cleaner.clean_frame(location)
|
|
132
|
+
return frame if frame
|
|
140
133
|
end
|
|
134
|
+
nil
|
|
141
135
|
end
|
|
142
136
|
|
|
143
137
|
def filter(name, value)
|
|
@@ -22,10 +22,12 @@ module ActiveRecord
|
|
|
22
22
|
# * change_table_comment (must supply a +:from+ and +:to+ option)
|
|
23
23
|
# * create_enum
|
|
24
24
|
# * create_join_table
|
|
25
|
+
# * create_virtual_table
|
|
25
26
|
# * create_table
|
|
26
27
|
# * disable_extension
|
|
27
28
|
# * drop_enum (must supply a list of values)
|
|
28
29
|
# * drop_join_table
|
|
30
|
+
# * drop_virtual_table (must supply options)
|
|
29
31
|
# * drop_table (must supply a block)
|
|
30
32
|
# * enable_extension
|
|
31
33
|
# * remove_column (must supply a type)
|
|
@@ -38,7 +40,7 @@ module ActiveRecord
|
|
|
38
40
|
# * remove_reference
|
|
39
41
|
# * remove_timestamps
|
|
40
42
|
# * rename_column
|
|
41
|
-
# * rename_enum
|
|
43
|
+
# * rename_enum
|
|
42
44
|
# * rename_enum_value (must supply a +:from+ and +:to+ option)
|
|
43
45
|
# * rename_index
|
|
44
46
|
# * rename_table
|
|
@@ -55,6 +57,8 @@ module ActiveRecord
|
|
|
55
57
|
:add_exclusion_constraint, :remove_exclusion_constraint,
|
|
56
58
|
:add_unique_constraint, :remove_unique_constraint,
|
|
57
59
|
:create_enum, :drop_enum, :rename_enum, :add_enum_value, :rename_enum_value,
|
|
60
|
+
:create_schema, :drop_schema,
|
|
61
|
+
:create_virtual_table, :drop_virtual_table
|
|
58
62
|
]
|
|
59
63
|
include JoinTable
|
|
60
64
|
|
|
@@ -163,7 +167,9 @@ module ActiveRecord
|
|
|
163
167
|
add_exclusion_constraint: :remove_exclusion_constraint,
|
|
164
168
|
add_unique_constraint: :remove_unique_constraint,
|
|
165
169
|
enable_extension: :disable_extension,
|
|
166
|
-
create_enum: :drop_enum
|
|
170
|
+
create_enum: :drop_enum,
|
|
171
|
+
create_schema: :drop_schema,
|
|
172
|
+
create_virtual_table: :drop_virtual_table
|
|
167
173
|
}.each do |cmd, inv|
|
|
168
174
|
[[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
|
|
169
175
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
|
@@ -196,13 +202,18 @@ module ActiveRecord
|
|
|
196
202
|
end
|
|
197
203
|
|
|
198
204
|
def invert_drop_table(args, &block)
|
|
199
|
-
|
|
200
|
-
|
|
205
|
+
options = args.extract_options!
|
|
206
|
+
options.delete(:if_exists)
|
|
207
|
+
|
|
208
|
+
if args.size > 1
|
|
209
|
+
raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given a single table name."
|
|
201
210
|
end
|
|
202
|
-
|
|
211
|
+
|
|
212
|
+
if args.size == 1 && options == {} && block == nil
|
|
203
213
|
raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
|
|
204
214
|
end
|
|
205
|
-
|
|
215
|
+
|
|
216
|
+
super(args.push(options), &block)
|
|
206
217
|
end
|
|
207
218
|
|
|
208
219
|
def invert_rename_table(args)
|
|
@@ -353,13 +364,13 @@ module ActiveRecord
|
|
|
353
364
|
end
|
|
354
365
|
|
|
355
366
|
def invert_rename_enum(args)
|
|
356
|
-
name,
|
|
367
|
+
name, new_name, = args
|
|
357
368
|
|
|
358
|
-
|
|
359
|
-
|
|
369
|
+
if new_name.is_a?(Hash) && new_name.key?(:to)
|
|
370
|
+
new_name = new_name[:to]
|
|
360
371
|
end
|
|
361
372
|
|
|
362
|
-
[:rename_enum, [
|
|
373
|
+
[:rename_enum, [new_name, name]]
|
|
363
374
|
end
|
|
364
375
|
|
|
365
376
|
def invert_rename_enum_value(args)
|
|
@@ -372,6 +383,12 @@ module ActiveRecord
|
|
|
372
383
|
[:rename_enum_value, [type_name, from: options[:to], to: options[:from]]]
|
|
373
384
|
end
|
|
374
385
|
|
|
386
|
+
def invert_drop_virtual_table(args)
|
|
387
|
+
_enum, values = args.dup.tap(&:extract_options!)
|
|
388
|
+
raise ActiveRecord::IrreversibleMigration, "drop_virtual_table is only reversible if given options." unless values
|
|
389
|
+
super
|
|
390
|
+
end
|
|
391
|
+
|
|
375
392
|
def respond_to_missing?(method, _)
|
|
376
393
|
super || delegate.respond_to?(method)
|
|
377
394
|
end
|
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
|
21
21
|
# New migration functionality that will never be backward compatible should be added directly to `ActiveRecord::Migration`.
|
|
22
22
|
#
|
|
23
23
|
# There are classes for each prior Rails version. Each class descends from the *next* Rails version, so:
|
|
24
|
-
# 5.2 < 6.0 < 6.1 < 7.0 < 7.1 < 7.2
|
|
24
|
+
# 5.2 < 6.0 < 6.1 < 7.0 < 7.1 < 7.2 < 8.0
|
|
25
25
|
#
|
|
26
26
|
# If you are introducing new migration functionality that should only apply from Rails 7 onward, then you should
|
|
27
27
|
# find the class that immediately precedes it (6.1), and override the relevant migration methods to undo your changes.
|
|
@@ -29,7 +29,10 @@ module ActiveRecord
|
|
|
29
29
|
# For example, Rails 6 added a default value for the `precision` option on datetime columns. So in this file, the `V5_2`
|
|
30
30
|
# class sets the value of `precision` to `nil` if it's not explicitly provided. This way, the default value will not apply
|
|
31
31
|
# for migrations written for 5.2, but will for migrations written for 6.0.
|
|
32
|
-
|
|
32
|
+
V8_0 = Current
|
|
33
|
+
|
|
34
|
+
class V7_2 < V8_0
|
|
35
|
+
end
|
|
33
36
|
|
|
34
37
|
class V7_1 < V7_2
|
|
35
38
|
end
|