activerecord 7.0.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1607 -1040
- data/MIT-LICENSE +1 -1
- data/README.rdoc +17 -18
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +18 -3
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +14 -6
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +17 -12
- data/lib/active_record/associations/collection_proxy.rb +22 -12
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +27 -17
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency.rb +20 -14
- data/lib/active_record/associations/preloader/association.rb +27 -6
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +345 -219
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/dirty.rb +40 -26
- data/lib/active_record/attribute_methods/primary_key.rb +76 -24
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +18 -5
- data/lib/active_record/attribute_methods/serialization.rb +172 -69
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +110 -28
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +56 -10
- data/lib/active_record/base.rb +10 -5
- data/lib/active_record/callbacks.rb +16 -32
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -34
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +164 -89
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +63 -43
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +128 -32
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +52 -8
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +163 -29
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +302 -129
- data/lib/active_record/connection_adapters/abstract/transaction.rb +287 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +504 -106
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +217 -104
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -144
- data/lib/active_record/connection_adapters/mysql/quoting.rb +29 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
- data/lib/active_record/connection_adapters/pool_config.rb +14 -5
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +72 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +41 -8
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +6 -10
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +358 -57
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +343 -181
- data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +45 -39
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +22 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +41 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +242 -81
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
- data/lib/active_record/connection_adapters.rb +3 -1
- data/lib/active_record/connection_handling.rb +73 -96
- data/lib/active_record/core.rb +136 -148
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -0
- data/lib/active_record/database_configurations/database_config.rb +9 -3
- data/lib/active_record/database_configurations/hash_config.rb +22 -12
- data/lib/active_record/database_configurations/url_config.rb +17 -11
- data/lib/active_record/database_configurations.rb +87 -34
- data/lib/active_record/delegated_type.rb +9 -4
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- data/lib/active_record/disable_joins_association_relation.rb +1 -1
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +13 -14
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +8 -4
- data/lib/active_record/encryption/derived_secret_key_provider.rb +9 -3
- data/lib/active_record/encryption/deterministic_key_provider.rb +1 -1
- data/lib/active_record/encryption/encryptable_record.rb +38 -22
- data/lib/active_record/encryption/encrypted_attribute_type.rb +19 -8
- data/lib/active_record/encryption/encryptor.rb +7 -7
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
- data/lib/active_record/encryption/extended_deterministic_queries.rb +83 -71
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message.rb +1 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +4 -4
- data/lib/active_record/encryption/scheme.rb +20 -23
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +114 -27
- data/lib/active_record/errors.rb +108 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +121 -73
- data/lib/active_record/future_result.rb +30 -5
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +55 -8
- data/lib/active_record/integration.rb +10 -10
- data/lib/active_record/internal_metadata.rb +118 -30
- data/lib/active_record/locking/optimistic.rb +32 -18
- data/lib/active_record/locking/pessimistic.rb +8 -5
- data/lib/active_record/log_subscriber.rb +39 -17
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +18 -13
- data/lib/active_record/middleware/shard_selector.rb +7 -5
- data/lib/active_record/migration/command_recorder.rb +104 -9
- data/lib/active_record/migration/compatibility.rb +158 -64
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration.rb +271 -117
- data/lib/active_record/model_schema.rb +82 -50
- data/lib/active_record/nested_attributes.rb +23 -3
- data/lib/active_record/normalization.rb +159 -0
- data/lib/active_record/persistence.rb +200 -47
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +87 -51
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +16 -3
- data/lib/active_record/railtie.rb +127 -61
- data/lib/active_record/railties/controller_runtime.rb +12 -8
- data/lib/active_record/railties/databases.rake +142 -143
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +177 -45
- data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
- data/lib/active_record/relation/batches.rb +190 -61
- data/lib/active_record/relation/calculations.rb +200 -83
- data/lib/active_record/relation/delegation.rb +23 -9
- data/lib/active_record/relation/finder_methods.rb +77 -16
- data/lib/active_record/relation/merger.rb +2 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +26 -14
- data/lib/active_record/relation/query_attribute.rb +25 -1
- data/lib/active_record/relation/query_methods.rb +429 -76
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +98 -41
- data/lib/active_record/result.rb +25 -9
- data/lib/active_record/runtime_registry.rb +10 -1
- data/lib/active_record/sanitization.rb +57 -16
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +65 -23
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +20 -12
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +5 -0
- data/lib/active_record/signed_id.rb +9 -7
- data/lib/active_record/store.rb +16 -11
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +138 -107
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +17 -15
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_fixtures.rb +123 -99
- data/lib/active_record/timestamp.rb +26 -14
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +39 -13
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +8 -4
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +3 -3
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +50 -5
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +143 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +1 -1
- data/lib/arel/nodes/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/filter.rb +1 -1
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +0 -8
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/predications.rb +2 -0
- data/lib/arel/table.rb +9 -5
- data/lib/arel/visitors/mysql.rb +8 -1
- data/lib/arel/visitors/to_sql.rb +81 -17
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +16 -2
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +50 -15
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
data/lib/active_record.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c)
|
4
|
+
# Copyright (c) David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -30,9 +30,11 @@ require "arel"
|
|
30
30
|
require "yaml"
|
31
31
|
|
32
32
|
require "active_record/version"
|
33
|
+
require "active_record/deprecator"
|
33
34
|
require "active_model/attribute_set"
|
34
35
|
require "active_record/errors"
|
35
36
|
|
37
|
+
# :include: activerecord/README.rdoc
|
36
38
|
module ActiveRecord
|
37
39
|
extend ActiveSupport::Autoload
|
38
40
|
|
@@ -47,18 +49,22 @@ module ActiveRecord
|
|
47
49
|
autoload :Encryption
|
48
50
|
autoload :Enum
|
49
51
|
autoload :Explain
|
52
|
+
autoload :FixtureSet, "active_record/fixtures"
|
50
53
|
autoload :Inheritance
|
51
54
|
autoload :Integration
|
52
55
|
autoload :InternalMetadata
|
56
|
+
autoload :LogSubscriber
|
57
|
+
autoload :Marshalling
|
53
58
|
autoload :Migration
|
54
59
|
autoload :Migrator, "active_record/migration"
|
55
60
|
autoload :ModelSchema
|
56
61
|
autoload :NestedAttributes
|
57
62
|
autoload :NoTouching
|
63
|
+
autoload :Normalization
|
58
64
|
autoload :Persistence
|
59
65
|
autoload :QueryCache
|
60
|
-
autoload :Querying
|
61
66
|
autoload :QueryLogs
|
67
|
+
autoload :Querying
|
62
68
|
autoload :ReadonlyAttributes
|
63
69
|
autoload :RecordInvalid, "active_record/validations"
|
64
70
|
autoload :Reflection
|
@@ -68,6 +74,7 @@ module ActiveRecord
|
|
68
74
|
autoload :SchemaDumper
|
69
75
|
autoload :SchemaMigration
|
70
76
|
autoload :Scoping
|
77
|
+
autoload :SecurePassword
|
71
78
|
autoload :SecureToken
|
72
79
|
autoload :Serialization
|
73
80
|
autoload :SignedId
|
@@ -76,6 +83,7 @@ module ActiveRecord
|
|
76
83
|
autoload :TestDatabases
|
77
84
|
autoload :TestFixtures, "active_record/fixtures"
|
78
85
|
autoload :Timestamp
|
86
|
+
autoload :TokenFor
|
79
87
|
autoload :TouchLater
|
80
88
|
autoload :Transactions
|
81
89
|
autoload :Translation
|
@@ -93,7 +101,7 @@ module ActiveRecord
|
|
93
101
|
autoload :DisableJoinsAssociationRelation
|
94
102
|
autoload :FutureResult
|
95
103
|
autoload :LegacyYamlAdapter
|
96
|
-
autoload :
|
104
|
+
autoload :Promise
|
97
105
|
autoload :Relation
|
98
106
|
autoload :Result
|
99
107
|
autoload :StatementCache
|
@@ -101,17 +109,18 @@ module ActiveRecord
|
|
101
109
|
autoload :Type
|
102
110
|
|
103
111
|
autoload_under "relation" do
|
104
|
-
autoload :
|
105
|
-
autoload :FinderMethods
|
112
|
+
autoload :Batches
|
106
113
|
autoload :Calculations
|
114
|
+
autoload :Delegation
|
115
|
+
autoload :FinderMethods
|
107
116
|
autoload :PredicateBuilder
|
117
|
+
autoload :QueryMethods
|
108
118
|
autoload :SpawnMethods
|
109
|
-
autoload :Batches
|
110
|
-
autoload :Delegation
|
111
119
|
end
|
112
120
|
end
|
113
121
|
|
114
122
|
module Coders
|
123
|
+
autoload :ColumnSerializer, "active_record/coders/column_serializer"
|
115
124
|
autoload :JSON, "active_record/coders/json"
|
116
125
|
autoload :YAMLColumn, "active_record/coders/yaml_column"
|
117
126
|
end
|
@@ -165,6 +174,9 @@ module ActiveRecord
|
|
165
174
|
autoload :SQLiteDatabaseTasks, "active_record/tasks/sqlite_database_tasks"
|
166
175
|
end
|
167
176
|
|
177
|
+
singleton_class.attr_accessor :disable_prepared_statements
|
178
|
+
self.disable_prepared_statements = false
|
179
|
+
|
168
180
|
# Lazily load the schema cache. This option will load the schema cache
|
169
181
|
# when a connection is established rather than on boot. If set,
|
170
182
|
# +config.active_record.use_schema_cache_dump+ will be set to false.
|
@@ -177,9 +189,6 @@ module ActiveRecord
|
|
177
189
|
singleton_class.attr_accessor :schema_cache_ignored_tables
|
178
190
|
self.schema_cache_ignored_tables = []
|
179
191
|
|
180
|
-
singleton_class.attr_accessor :legacy_connection_handling
|
181
|
-
self.legacy_connection_handling = true
|
182
|
-
|
183
192
|
singleton_class.attr_reader :default_timezone
|
184
193
|
|
185
194
|
# Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
|
@@ -194,12 +203,53 @@ module ActiveRecord
|
|
194
203
|
|
195
204
|
self.default_timezone = :utc
|
196
205
|
|
206
|
+
# The action to take when database query produces warning.
|
207
|
+
# Must be one of :ignore, :log, :raise, :report, or a custom proc.
|
208
|
+
# The default is :ignore.
|
209
|
+
singleton_class.attr_reader :db_warnings_action
|
210
|
+
|
211
|
+
def self.db_warnings_action=(action)
|
212
|
+
@db_warnings_action =
|
213
|
+
case action
|
214
|
+
when :ignore
|
215
|
+
nil
|
216
|
+
when :log
|
217
|
+
->(warning) do
|
218
|
+
warning_message = "[#{warning.class}] #{warning.message}"
|
219
|
+
warning_message += " (#{warning.code})" if warning.code
|
220
|
+
ActiveRecord::Base.logger.warn(warning_message)
|
221
|
+
end
|
222
|
+
when :raise
|
223
|
+
->(warning) { raise warning }
|
224
|
+
when :report
|
225
|
+
->(warning) { Rails.error.report(warning, handled: true) }
|
226
|
+
when Proc
|
227
|
+
action
|
228
|
+
else
|
229
|
+
raise ArgumentError, "db_warnings_action must be one of :ignore, :log, :raise, :report, or a custom proc."
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
self.db_warnings_action = :ignore
|
234
|
+
|
235
|
+
# Specify allowlist of database warnings.
|
236
|
+
singleton_class.attr_accessor :db_warnings_ignore
|
237
|
+
self.db_warnings_ignore = []
|
238
|
+
|
197
239
|
singleton_class.attr_accessor :writing_role
|
198
240
|
self.writing_role = :writing
|
199
241
|
|
200
242
|
singleton_class.attr_accessor :reading_role
|
201
243
|
self.reading_role = :reading
|
202
244
|
|
245
|
+
def self.legacy_connection_handling=(_)
|
246
|
+
raise ArgumentError, <<~MSG.squish
|
247
|
+
The `legacy_connection_handling` setter was deprecated in 7.0 and removed in 7.1,
|
248
|
+
but is still defined in your configuration. Please remove this call as it no longer
|
249
|
+
has any effect."
|
250
|
+
MSG
|
251
|
+
end
|
252
|
+
|
203
253
|
# Sets the async_query_executor for an application. By default the thread pool executor
|
204
254
|
# set to +nil+ which will not run queries in the background. Applications must configure
|
205
255
|
# a thread pool executor to use this feature. Options are:
|
@@ -258,6 +308,21 @@ module ActiveRecord
|
|
258
308
|
singleton_class.attr_accessor :maintain_test_schema
|
259
309
|
self.maintain_test_schema = nil
|
260
310
|
|
311
|
+
singleton_class.attr_accessor :raise_on_assign_to_attr_readonly
|
312
|
+
self.raise_on_assign_to_attr_readonly = false
|
313
|
+
|
314
|
+
singleton_class.attr_accessor :belongs_to_required_validates_foreign_key
|
315
|
+
self.belongs_to_required_validates_foreign_key = true
|
316
|
+
|
317
|
+
singleton_class.attr_accessor :before_committed_on_all_records
|
318
|
+
self.before_committed_on_all_records = false
|
319
|
+
|
320
|
+
singleton_class.attr_accessor :run_after_transaction_callbacks_in_order_defined
|
321
|
+
self.run_after_transaction_callbacks_in_order_defined = false
|
322
|
+
|
323
|
+
singleton_class.attr_accessor :commit_transaction_on_non_local_return
|
324
|
+
self.commit_transaction_on_non_local_return = false
|
325
|
+
|
261
326
|
##
|
262
327
|
# :singleton-method:
|
263
328
|
# Specify a threshold for the size of query result sets. If the number of
|
@@ -302,6 +367,12 @@ module ActiveRecord
|
|
302
367
|
singleton_class.attr_accessor :timestamped_migrations
|
303
368
|
self.timestamped_migrations = true
|
304
369
|
|
370
|
+
##
|
371
|
+
# :singleton-method:
|
372
|
+
# Specify strategy to use for executing migrations.
|
373
|
+
singleton_class.attr_accessor :migration_strategy
|
374
|
+
self.migration_strategy = Migration::DefaultStrategy
|
375
|
+
|
305
376
|
##
|
306
377
|
# :singleton-method:
|
307
378
|
# Specify whether schema dump should happen at the end of the
|
@@ -321,12 +392,19 @@ module ActiveRecord
|
|
321
392
|
singleton_class.attr_accessor :dump_schemas
|
322
393
|
self.dump_schemas = :schema_search_path
|
323
394
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
395
|
+
def self.suppress_multiple_database_warning
|
396
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
397
|
+
config.active_record.suppress_multiple_database_warning is deprecated and will be removed in Rails 7.2.
|
398
|
+
It no longer has any effect and should be removed from the configuration file.
|
399
|
+
MSG
|
400
|
+
end
|
401
|
+
|
402
|
+
def self.suppress_multiple_database_warning=(value)
|
403
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
404
|
+
config.active_record.suppress_multiple_database_warning= is deprecated and will be removed in Rails 7.2.
|
405
|
+
It no longer has any effect and should be removed from the configuration file.
|
406
|
+
MSG
|
407
|
+
end
|
330
408
|
|
331
409
|
##
|
332
410
|
# :singleton-method:
|
@@ -337,9 +415,53 @@ module ActiveRecord
|
|
337
415
|
singleton_class.attr_accessor :verify_foreign_keys_for_fixtures
|
338
416
|
self.verify_foreign_keys_for_fixtures = false
|
339
417
|
|
418
|
+
##
|
419
|
+
# :singleton-method:
|
420
|
+
# If true, Rails will continue allowing plural association names in where clauses on singular associations
|
421
|
+
# This behavior will be removed in Rails 7.2.
|
422
|
+
singleton_class.attr_accessor :allow_deprecated_singular_associations_name
|
423
|
+
self.allow_deprecated_singular_associations_name = true
|
424
|
+
|
340
425
|
singleton_class.attr_accessor :query_transformers
|
341
426
|
self.query_transformers = []
|
342
427
|
|
428
|
+
##
|
429
|
+
# :singleton-method:
|
430
|
+
# Application configurable boolean that instructs the YAML Coder to use
|
431
|
+
# an unsafe load if set to true.
|
432
|
+
singleton_class.attr_accessor :use_yaml_unsafe_load
|
433
|
+
self.use_yaml_unsafe_load = false
|
434
|
+
|
435
|
+
##
|
436
|
+
# :singleton-method:
|
437
|
+
# Application configurable boolean that denotes whether or not to raise
|
438
|
+
# an exception when the PostgreSQLAdapter is provided with an integer that
|
439
|
+
# is wider than signed 64bit representation
|
440
|
+
singleton_class.attr_accessor :raise_int_wider_than_64bit
|
441
|
+
self.raise_int_wider_than_64bit = true
|
442
|
+
|
443
|
+
##
|
444
|
+
# :singleton-method:
|
445
|
+
# Application configurable array that provides additional permitted classes
|
446
|
+
# to Psych safe_load in the YAML Coder
|
447
|
+
singleton_class.attr_accessor :yaml_column_permitted_classes
|
448
|
+
self.yaml_column_permitted_classes = [Symbol]
|
449
|
+
|
450
|
+
##
|
451
|
+
# :singleton-method:
|
452
|
+
# Controls when to generate a value for <tt>has_secure_token</tt>
|
453
|
+
# declarations. Defaults to <tt>:create</tt>.
|
454
|
+
singleton_class.attr_accessor :generate_secure_token_on
|
455
|
+
self.generate_secure_token_on = :create
|
456
|
+
|
457
|
+
def self.marshalling_format_version
|
458
|
+
Marshalling.format_version
|
459
|
+
end
|
460
|
+
|
461
|
+
def self.marshalling_format_version=(value)
|
462
|
+
Marshalling.format_version = value
|
463
|
+
end
|
464
|
+
|
343
465
|
def self.eager_load!
|
344
466
|
super
|
345
467
|
ActiveRecord::Locking.eager_load!
|
@@ -349,6 +471,11 @@ module ActiveRecord
|
|
349
471
|
ActiveRecord::ConnectionAdapters.eager_load!
|
350
472
|
ActiveRecord::Encryption.eager_load!
|
351
473
|
end
|
474
|
+
|
475
|
+
# Explicitly closes all database connections in all pools.
|
476
|
+
def self.disconnect_all!
|
477
|
+
ConnectionAdapters::PoolConfig.disconnect_all!
|
478
|
+
end
|
352
479
|
end
|
353
480
|
|
354
481
|
ActiveSupport.on_load(:active_record) do
|
data/lib/arel/errors.rb
CHANGED
data/lib/arel/factory_methods.rb
CHANGED
data/lib/arel/nodes/and.rb
CHANGED
data/lib/arel/nodes/binary.rb
CHANGED
@@ -39,6 +39,12 @@ module Arel # :nodoc: all
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
class As < Binary
|
43
|
+
def to_cte
|
44
|
+
Arel::Nodes::Cte.new(left.name, right)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
42
48
|
class Between < Binary; include FetchAttribute; end
|
43
49
|
|
44
50
|
class GreaterThan < Binary
|
@@ -112,7 +118,6 @@ module Arel # :nodoc: all
|
|
112
118
|
end
|
113
119
|
|
114
120
|
%w{
|
115
|
-
As
|
116
121
|
Assignment
|
117
122
|
Join
|
118
123
|
Union
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arel # :nodoc: all
|
4
|
+
module Nodes
|
5
|
+
class BoundSqlLiteral < NodeExpression
|
6
|
+
attr_reader :sql_with_placeholders, :positional_binds, :named_binds
|
7
|
+
|
8
|
+
def initialize(sql_with_placeholders, positional_binds, named_binds)
|
9
|
+
if !positional_binds.empty? && !named_binds.empty?
|
10
|
+
raise BindError.new("cannot mix positional and named binds", sql_with_placeholders)
|
11
|
+
elsif !positional_binds.empty?
|
12
|
+
if positional_binds.size != (expected = sql_with_placeholders.count("?"))
|
13
|
+
raise BindError.new("wrong number of bind variables (#{positional_binds.size} for #{expected})", sql_with_placeholders)
|
14
|
+
end
|
15
|
+
elsif !named_binds.empty?
|
16
|
+
tokens_in_string = sql_with_placeholders.scan(/:(?<!::)([a-zA-Z]\w*)/).flatten.map(&:to_sym).uniq
|
17
|
+
tokens_in_hash = named_binds.keys.map(&:to_sym).uniq
|
18
|
+
|
19
|
+
if !(missing = (tokens_in_string - tokens_in_hash)).empty?
|
20
|
+
if missing.size == 1
|
21
|
+
raise BindError.new("missing value for #{missing.first.inspect}", sql_with_placeholders)
|
22
|
+
else
|
23
|
+
raise BindError.new("missing values for #{missing.inspect}", sql_with_placeholders)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
@sql_with_placeholders = sql_with_placeholders
|
29
|
+
if !positional_binds.empty?
|
30
|
+
@positional_binds = positional_binds
|
31
|
+
@named_binds = nil
|
32
|
+
else
|
33
|
+
@positional_binds = nil
|
34
|
+
@named_binds = named_binds
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def hash
|
39
|
+
[self.class, sql_with_placeholders, positional_binds, named_binds].hash
|
40
|
+
end
|
41
|
+
|
42
|
+
def eql?(other)
|
43
|
+
self.class == other.class &&
|
44
|
+
sql_with_placeholders == other.sql_with_placeholders &&
|
45
|
+
positional_binds == other.positional_binds &&
|
46
|
+
named_binds == other.named_binds
|
47
|
+
end
|
48
|
+
alias :== :eql?
|
49
|
+
|
50
|
+
def +(other)
|
51
|
+
raise ArgumentError, "Expected Arel node" unless Arel.arel_node?(other)
|
52
|
+
|
53
|
+
Fragments.new([self, other])
|
54
|
+
end
|
55
|
+
|
56
|
+
def inspect
|
57
|
+
"#<#{self.class.name} #{sql_with_placeholders.inspect} #{(named_binds || positional_binds).inspect}>"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arel # :nodoc: all
|
4
|
+
module Nodes
|
5
|
+
class Cte < Arel::Nodes::Binary
|
6
|
+
alias :name :left
|
7
|
+
alias :relation :right
|
8
|
+
attr_reader :materialized
|
9
|
+
|
10
|
+
def initialize(name, relation, materialized: nil)
|
11
|
+
super(name, relation)
|
12
|
+
@materialized = materialized
|
13
|
+
end
|
14
|
+
|
15
|
+
def hash
|
16
|
+
[name, relation, materialized].hash
|
17
|
+
end
|
18
|
+
|
19
|
+
def eql?(other)
|
20
|
+
self.class == other.class &&
|
21
|
+
self.name == other.name &&
|
22
|
+
self.relation == other.relation &&
|
23
|
+
self.materialized == other.materialized
|
24
|
+
end
|
25
|
+
alias :== :eql?
|
26
|
+
|
27
|
+
def to_cte
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_table
|
32
|
+
Arel::Table.new(name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/arel/nodes/filter.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arel # :nodoc: all
|
4
|
+
module Nodes
|
5
|
+
class Fragments < Arel::Nodes::Node
|
6
|
+
attr_reader :values
|
7
|
+
|
8
|
+
def initialize(values = [])
|
9
|
+
super()
|
10
|
+
@values = values
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize_copy(other)
|
14
|
+
super
|
15
|
+
@values = @values.clone
|
16
|
+
end
|
17
|
+
|
18
|
+
def hash
|
19
|
+
[@values].hash
|
20
|
+
end
|
21
|
+
|
22
|
+
def +(other)
|
23
|
+
raise ArgumentError, "Expected Arel node" unless Arel.arel_node?(other)
|
24
|
+
|
25
|
+
self.class.new([*@values, other])
|
26
|
+
end
|
27
|
+
|
28
|
+
def eql?(other)
|
29
|
+
self.class == other.class &&
|
30
|
+
self.values == other.values
|
31
|
+
end
|
32
|
+
alias :== :eql?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -36,14 +36,6 @@ module Arel # :nodoc: all
|
|
36
36
|
attribute.quoted_array(values)
|
37
37
|
end
|
38
38
|
|
39
|
-
def table_name
|
40
|
-
attribute.relation.table_alias || attribute.relation.name
|
41
|
-
end
|
42
|
-
|
43
|
-
def column_name
|
44
|
-
attribute.name
|
45
|
-
end
|
46
|
-
|
47
39
|
def casted_values
|
48
40
|
type = attribute.type_caster
|
49
41
|
|
data/lib/arel/nodes/node.rb
CHANGED
@@ -2,8 +2,117 @@
|
|
2
2
|
|
3
3
|
module Arel # :nodoc: all
|
4
4
|
module Nodes
|
5
|
-
|
6
|
-
#
|
5
|
+
# = Using +Arel::Nodes::Node+
|
6
|
+
#
|
7
|
+
# Active Record uses Arel to compose SQL statements. Instead of building SQL strings directly, it's building an
|
8
|
+
# abstract syntax tree (AST) of the statement using various types of Arel::Nodes::Node. Each node represents a
|
9
|
+
# fragment of a SQL statement.
|
10
|
+
#
|
11
|
+
# The intermediate representation allows Arel to compile the statement into the database's specific SQL dialect
|
12
|
+
# only before sending it without having to care about the nuances of each database when building the statement.
|
13
|
+
# It also allows easier composition of statements without having to resort to (brittle and unsafe) string manipulation.
|
14
|
+
#
|
15
|
+
# == Building constraints
|
16
|
+
#
|
17
|
+
# One of the most common use cases of Arel is generating constraints for +SELECT+ statements. To help with that,
|
18
|
+
# most nodes include a couple of useful factory methods to create subtree structures for common constraints. For
|
19
|
+
# a full list of those, please refer to Arel::Predications.
|
20
|
+
#
|
21
|
+
# The following example creates an equality constraint where the value of the name column on the users table
|
22
|
+
# matches the value DHH.
|
23
|
+
#
|
24
|
+
# users = Arel::Table.new(:users)
|
25
|
+
# constraint = users[:name].eq("DHH")
|
26
|
+
#
|
27
|
+
# # => Arel::Nodes::Equality.new(
|
28
|
+
# # Arel::Attributes::Attribute.new(users, "name"),
|
29
|
+
# # Arel::Nodes::Casted.new(
|
30
|
+
# # "DHH",
|
31
|
+
# # Arel::Attributes::Attribute.new(users, "name")
|
32
|
+
# # )
|
33
|
+
# # )
|
34
|
+
#
|
35
|
+
# The resulting SQL fragment will look like this:
|
36
|
+
#
|
37
|
+
# "users"."name" = 'DHH'
|
38
|
+
#
|
39
|
+
# The constraint fragments can be used with regular ActiveRecord::Relation objects instead of a Hash. The
|
40
|
+
# following two examples show two ways of creating the same query.
|
41
|
+
#
|
42
|
+
# User.where(name: 'DHH')
|
43
|
+
#
|
44
|
+
# # SELECT "users".* FROM "users" WHERE "users"."name" = 'DHH'
|
45
|
+
#
|
46
|
+
# users = User.arel_table
|
47
|
+
#
|
48
|
+
# User.where(users[:name].eq('DHH'))
|
49
|
+
#
|
50
|
+
# # SELECT "users".* FROM "users" WHERE "users"."name" = 'DHH'
|
51
|
+
#
|
52
|
+
# == Functions
|
53
|
+
#
|
54
|
+
# Arel comes with built-in support for SQL functions like +COUNT+, +SUM+, +MIN+, +MAX+, and +AVG+. The
|
55
|
+
# Arel::Expressions module includes factory methods for the default functions.
|
56
|
+
#
|
57
|
+
# employees = Employee.arel_table
|
58
|
+
#
|
59
|
+
# Employee.select(employees[:department_id], employees[:salary].average).group(employees[:department_id])
|
60
|
+
#
|
61
|
+
# # SELECT "employees"."department_id", AVG("employees"."salary")
|
62
|
+
# # FROM "employees" GROUP BY "employees"."department_id"
|
63
|
+
#
|
64
|
+
# It’s also possible to use custom functions by using the Arel::Nodes::NamedFunction node type. It accepts a
|
65
|
+
# function name and an array of parameters.
|
66
|
+
#
|
67
|
+
# Arel::Nodes::NamedFunction.new('date_trunc', [Arel::Nodes.build_quoted('day'), User.arel_table[:created_at]])
|
68
|
+
#
|
69
|
+
# # date_trunc('day', "users"."created_at")
|
70
|
+
#
|
71
|
+
# == Quoting & bind params
|
72
|
+
#
|
73
|
+
# Values that you pass to Arel nodes need to be quoted or wrapped in bind params. This ensures they are properly
|
74
|
+
# converted into the correct format without introducing a possible SQL injection vulnerability. Most factory
|
75
|
+
# methods (like +eq+, +gt+, +lteq+, …) quote passed values automatically. When not using a factory method, it’s
|
76
|
+
# possible to convert a value and wrap it in an Arel::Nodes::Quoted node (if necessary) by calling +Arel::Nodes.
|
77
|
+
# build_quoted+.
|
78
|
+
#
|
79
|
+
# Arel::Nodes.build_quoted("foo") # 'foo'
|
80
|
+
# Arel::Nodes.build_quoted(12.3) # 12.3
|
81
|
+
#
|
82
|
+
# Instead of quoting values and embedding them directly in the SQL statement, it’s also possible to create bind
|
83
|
+
# params. This keeps the actual values outside of the statement and allows using the prepared statement feature
|
84
|
+
# of some databases.
|
85
|
+
#
|
86
|
+
# attribute = ActiveRecord::Relation::QueryAttribute.new(:name, "DHH", ActiveRecord::Type::String.new)
|
87
|
+
# Arel::Nodes::BindParam.new(attribute)
|
88
|
+
#
|
89
|
+
# When ActiveRecord runs the query, bind params are replaced by placeholders (like +$1+) and the values are passed
|
90
|
+
# separately.
|
91
|
+
#
|
92
|
+
# == SQL Literals
|
93
|
+
#
|
94
|
+
# For cases where there is no way to represent a particular SQL fragment using Arel nodes, you can use an SQL
|
95
|
+
# literal. SQL literals are strings that Arel will treat “as is”.
|
96
|
+
#
|
97
|
+
# Arel.sql('LOWER("users"."name")').eq('dhh')
|
98
|
+
#
|
99
|
+
# # LOWER("users"."name") = 'dhh'
|
100
|
+
#
|
101
|
+
# Please keep in mind that passing data as raw SQL literals might introduce a possible SQL injection. However,
|
102
|
+
# `Arel.sql` supports binding parameters which will ensure proper quoting. This can be useful when you need to
|
103
|
+
# control the exact SQL you run, but you still have potentially user-supplied values.
|
104
|
+
#
|
105
|
+
# Arel.sql('LOWER("users"."name") = ?', 'dhh')
|
106
|
+
#
|
107
|
+
# # LOWER("users"."name") = 'dhh'
|
108
|
+
#
|
109
|
+
# You can also combine SQL literals.
|
110
|
+
#
|
111
|
+
# sql = Arel.sql('SELECT * FROM "users" WHERE ')
|
112
|
+
# sql += Arel.sql('LOWER("users"."name") = :name', name: 'dhh')
|
113
|
+
# sql += Arel.sql('AND "users"."age" > :age', age: 35)
|
114
|
+
#
|
115
|
+
# # SELECT * FROM "users" WHERE LOWER("users"."name") = 'dhh' AND "users"."age" > '35'
|
7
116
|
class Node
|
8
117
|
include Arel::FactoryMethods
|
9
118
|
|