activerecord 8.0.0 → 8.1.4
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 +1381 -241
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -17
- data/lib/active_record/associations/association_scope.rb +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +20 -4
- data/lib/active_record/associations/builder/association.rb +16 -5
- data/lib/active_record/associations/builder/belongs_to.rb +36 -8
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +9 -5
- data/lib/active_record/associations/collection_proxy.rb +26 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/foreign_association.rb +3 -1
- data/lib/active_record/associations/has_one_association.rb +1 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +5 -4
- data/lib/active_record/associations/preloader/association.rb +1 -1
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations.rb +159 -21
- data/lib/active_record/attribute_methods/primary_key.rb +2 -1
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +19 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +10 -2
- data/lib/active_record/attribute_methods.rb +24 -17
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +22 -12
- data/lib/active_record/base.rb +3 -4
- data/lib/active_record/callbacks.rb +1 -2
- data/lib/active_record/coders/column_serializer.rb +1 -1
- data/lib/active_record/coders/json.rb +16 -6
- data/lib/active_record/coders/yaml_column.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +19 -18
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +68 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +474 -112
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +68 -41
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -24
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +31 -35
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +94 -28
- data/lib/active_record/connection_adapters/abstract/transaction.rb +25 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -64
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +133 -40
- data/lib/active_record/connection_adapters/column.rb +14 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +42 -5
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +40 -25
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +66 -15
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +9 -3
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +29 -33
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +46 -3
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -33
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +70 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +99 -54
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +40 -12
- data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +39 -23
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +15 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +7 -14
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +68 -37
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +8 -3
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +16 -2
- data/lib/active_record/connection_adapters.rb +1 -0
- data/lib/active_record/connection_handling.rb +15 -10
- data/lib/active_record/core.rb +44 -12
- data/lib/active_record/counter_cache.rb +36 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +5 -1
- data/lib/active_record/database_configurations/hash_config.rb +66 -9
- data/lib/active_record/database_configurations/url_config.rb +15 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- data/lib/active_record/disable_joins_association_relation.rb +5 -1
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/encryptable_record.rb +5 -5
- data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
- data/lib/active_record/encryption/encrypted_fixtures.rb +12 -7
- data/lib/active_record/encryption/encryptor.rb +39 -25
- data/lib/active_record/encryption/scheme.rb +1 -1
- data/lib/active_record/enum.rb +37 -20
- data/lib/active_record/errors.rb +23 -7
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +76 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -2
- data/lib/active_record/future_result.rb +5 -3
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +9 -4
- data/lib/active_record/insert_all.rb +14 -9
- data/lib/active_record/locking/optimistic.rb +7 -0
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +30 -22
- data/lib/active_record/message_pack.rb +13 -0
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +32 -6
- data/lib/active_record/migration/compatibility.rb +34 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +31 -21
- data/lib/active_record/model_schema.rb +38 -12
- data/lib/active_record/nested_attributes.rb +10 -6
- data/lib/active_record/persistence.rb +35 -3
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +7 -7
- data/lib/active_record/querying.rb +17 -5
- data/lib/active_record/railtie.rb +35 -6
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +24 -20
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +36 -1
- data/lib/active_record/relation/batches.rb +25 -11
- data/lib/active_record/relation/calculations.rb +62 -41
- data/lib/active_record/relation/delegation.rb +0 -1
- data/lib/active_record/relation/finder_methods.rb +76 -45
- data/lib/active_record/relation/merger.rb +4 -2
- data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +7 -7
- data/lib/active_record/relation/predicate_builder.rb +10 -8
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +106 -45
- data/lib/active_record/relation/spawn_methods.rb +6 -6
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +63 -31
- data/lib/active_record/result.rb +44 -21
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +2 -0
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +41 -21
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +48 -19
- data/lib/active_record/statement_cache.rb +16 -12
- data/lib/active_record/store.rb +46 -19
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +5 -20
- data/lib/active_record/tasks/abstract_tasks.rb +83 -0
- data/lib/active_record/tasks/database_tasks.rb +44 -45
- data/lib/active_record/tasks/mysql_database_tasks.rb +4 -56
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -26
- data/lib/active_record/test_databases.rb +18 -4
- data/lib/active_record/test_fixtures.rb +40 -6
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +58 -32
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +13 -2
- data/lib/active_record/type/serialized.rb +16 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record.rb +72 -7
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +1 -1
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/predications.rb +1 -3
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +7 -23
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +16 -15
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
|
@@ -15,7 +15,9 @@ module ActiveRecord
|
|
|
15
15
|
elsif @type.serialized?
|
|
16
16
|
value_for_database
|
|
17
17
|
elsif @type.mutable? # If the type is simply mutable, we deep_dup it.
|
|
18
|
-
|
|
18
|
+
unless @value_before_type_cast.frozen?
|
|
19
|
+
@value_before_type_cast = @value_before_type_cast.deep_dup
|
|
20
|
+
end
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
|
|
@@ -35,7 +37,7 @@ module ActiveRecord
|
|
|
35
37
|
def nil?
|
|
36
38
|
unless value_before_type_cast.is_a?(StatementCache::Substitute)
|
|
37
39
|
value_before_type_cast.nil? ||
|
|
38
|
-
type.respond_to?(:subtype) && serializable? && value_for_database.nil?
|
|
40
|
+
(type.respond_to?(:subtype) || type.respond_to?(:normalizer)) && serializable? && value_for_database.nil?
|
|
39
41
|
end
|
|
40
42
|
end
|
|
41
43
|
|
|
@@ -510,7 +510,7 @@ module ActiveRecord
|
|
|
510
510
|
# # WITH RECURSIVE post_and_replies AS (
|
|
511
511
|
# # (SELECT * FROM posts WHERE id = 42)
|
|
512
512
|
# # UNION ALL
|
|
513
|
-
# # (SELECT * FROM posts JOIN
|
|
513
|
+
# # (SELECT * FROM posts JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id)
|
|
514
514
|
# # )
|
|
515
515
|
# # SELECT * FROM posts
|
|
516
516
|
#
|
|
@@ -576,7 +576,7 @@ module ActiveRecord
|
|
|
576
576
|
end
|
|
577
577
|
|
|
578
578
|
def group!(*args) # :nodoc:
|
|
579
|
-
self.group_values
|
|
579
|
+
self.group_values |= args
|
|
580
580
|
self
|
|
581
581
|
end
|
|
582
582
|
|
|
@@ -721,8 +721,16 @@ module ActiveRecord
|
|
|
721
721
|
references = column_references([column])
|
|
722
722
|
self.references_values |= references unless references.empty?
|
|
723
723
|
|
|
724
|
-
|
|
725
|
-
|
|
724
|
+
if column.is_a?(Arel::Nodes::SqlLiteral)
|
|
725
|
+
arel_column = column
|
|
726
|
+
else
|
|
727
|
+
arel_column = order_column(column.to_s)
|
|
728
|
+
|
|
729
|
+
unless arel_column.is_a?(Arel::Nodes::SqlLiteral)
|
|
730
|
+
values = cast_values_for_in_order_of(values, arel_column.type_caster)
|
|
731
|
+
end
|
|
732
|
+
return spawn.none! if values.empty?
|
|
733
|
+
end
|
|
726
734
|
|
|
727
735
|
scope = spawn.order!(build_case_for_value_position(arel_column, values, filter: filter))
|
|
728
736
|
|
|
@@ -809,7 +817,7 @@ module ActiveRecord
|
|
|
809
817
|
end
|
|
810
818
|
|
|
811
819
|
def unscope!(*args) # :nodoc:
|
|
812
|
-
self.unscope_values
|
|
820
|
+
self.unscope_values |= args
|
|
813
821
|
|
|
814
822
|
args.each do |scope|
|
|
815
823
|
case scope
|
|
@@ -837,6 +845,26 @@ module ActiveRecord
|
|
|
837
845
|
self
|
|
838
846
|
end
|
|
839
847
|
|
|
848
|
+
def table_name_qualified_unscope_values
|
|
849
|
+
self.unscope_values.map do |scope|
|
|
850
|
+
case scope
|
|
851
|
+
when Hash
|
|
852
|
+
scope.transform_values do |target_value|
|
|
853
|
+
case target_value
|
|
854
|
+
when Array
|
|
855
|
+
target_value.map { |value| qualify_attribute_with_table_name(value) }
|
|
856
|
+
when Symbol, String
|
|
857
|
+
qualify_attribute_with_table_name(target_value)
|
|
858
|
+
else
|
|
859
|
+
target_value
|
|
860
|
+
end
|
|
861
|
+
end
|
|
862
|
+
else
|
|
863
|
+
scope
|
|
864
|
+
end
|
|
865
|
+
end
|
|
866
|
+
end
|
|
867
|
+
|
|
840
868
|
# Performs JOINs on +args+. The given symbol(s) should match the name of
|
|
841
869
|
# the association(s).
|
|
842
870
|
#
|
|
@@ -1048,13 +1076,13 @@ module ActiveRecord
|
|
|
1048
1076
|
# Allows you to change a previously set where condition for a given attribute, instead of appending to that condition.
|
|
1049
1077
|
#
|
|
1050
1078
|
# Post.where(trashed: true).where(trashed: false)
|
|
1051
|
-
# # WHERE `trashed` =
|
|
1079
|
+
# # WHERE `trashed` = true AND `trashed` = false
|
|
1052
1080
|
#
|
|
1053
1081
|
# Post.where(trashed: true).rewhere(trashed: false)
|
|
1054
|
-
# # WHERE `trashed` =
|
|
1082
|
+
# # WHERE `trashed` = false
|
|
1055
1083
|
#
|
|
1056
1084
|
# Post.where(active: true).where(trashed: true).rewhere(trashed: false)
|
|
1057
|
-
# # WHERE `active` =
|
|
1085
|
+
# # WHERE `active` = true AND `trashed` = false
|
|
1058
1086
|
#
|
|
1059
1087
|
# This is short-hand for <tt>unscope(where: conditions.keys).where(conditions)</tt>.
|
|
1060
1088
|
# Note that unlike reorder, we're only unscoping the named conditions -- not the entire where statement.
|
|
@@ -1076,16 +1104,16 @@ module ActiveRecord
|
|
|
1076
1104
|
# end
|
|
1077
1105
|
#
|
|
1078
1106
|
# User.where(accepted: true)
|
|
1079
|
-
# # WHERE `accepted` =
|
|
1107
|
+
# # WHERE `accepted` = true
|
|
1080
1108
|
#
|
|
1081
1109
|
# User.where(accepted: true).invert_where
|
|
1082
|
-
# # WHERE `accepted` !=
|
|
1110
|
+
# # WHERE `accepted` != true
|
|
1083
1111
|
#
|
|
1084
1112
|
# User.active
|
|
1085
|
-
# # WHERE `accepted` =
|
|
1113
|
+
# # WHERE `accepted` = true AND `locked` = false
|
|
1086
1114
|
#
|
|
1087
1115
|
# User.active.invert_where
|
|
1088
|
-
# # WHERE NOT (`accepted` =
|
|
1116
|
+
# # WHERE NOT (`accepted` = true AND `locked` = false)
|
|
1089
1117
|
#
|
|
1090
1118
|
# Be careful because this inverts all conditions before +invert_where+ call.
|
|
1091
1119
|
#
|
|
@@ -1096,7 +1124,7 @@ module ActiveRecord
|
|
|
1096
1124
|
#
|
|
1097
1125
|
# # It also inverts `where(role: 'admin')` unexpectedly.
|
|
1098
1126
|
# User.where(role: 'admin').inactive
|
|
1099
|
-
# # WHERE NOT (`role` = 'admin' AND `accepted` =
|
|
1127
|
+
# # WHERE NOT (`role` = 'admin' AND `accepted` = true AND `locked` = false)
|
|
1100
1128
|
#
|
|
1101
1129
|
def invert_where
|
|
1102
1130
|
spawn.invert_where!
|
|
@@ -1213,6 +1241,7 @@ module ActiveRecord
|
|
|
1213
1241
|
end
|
|
1214
1242
|
|
|
1215
1243
|
def limit!(value) # :nodoc:
|
|
1244
|
+
value = Integer(value) unless value.nil?
|
|
1216
1245
|
self.limit_value = value
|
|
1217
1246
|
self
|
|
1218
1247
|
end
|
|
@@ -1299,13 +1328,13 @@ module ActiveRecord
|
|
|
1299
1328
|
#
|
|
1300
1329
|
# users = User.readonly
|
|
1301
1330
|
# users.first.save
|
|
1302
|
-
# => ActiveRecord::ReadOnlyRecord: User is marked as readonly
|
|
1331
|
+
# # => ActiveRecord::ReadOnlyRecord: User is marked as readonly
|
|
1303
1332
|
#
|
|
1304
1333
|
# To make a readonly relation writable, pass +false+.
|
|
1305
1334
|
#
|
|
1306
1335
|
# users.readonly(false)
|
|
1307
1336
|
# users.first.save
|
|
1308
|
-
# => true
|
|
1337
|
+
# # => true
|
|
1309
1338
|
def readonly(value = true)
|
|
1310
1339
|
spawn.readonly!(value)
|
|
1311
1340
|
end
|
|
@@ -1320,7 +1349,7 @@ module ActiveRecord
|
|
|
1320
1349
|
#
|
|
1321
1350
|
# user = User.strict_loading.first
|
|
1322
1351
|
# user.comments.to_a
|
|
1323
|
-
# => ActiveRecord::StrictLoadingViolationError
|
|
1352
|
+
# # => ActiveRecord::StrictLoadingViolationError
|
|
1324
1353
|
def strict_loading(value = true)
|
|
1325
1354
|
spawn.strict_loading!(value)
|
|
1326
1355
|
end
|
|
@@ -1465,7 +1494,7 @@ module ActiveRecord
|
|
|
1465
1494
|
modules << Module.new(&block) if block
|
|
1466
1495
|
modules.flatten!
|
|
1467
1496
|
|
|
1468
|
-
self.extending_values
|
|
1497
|
+
self.extending_values |= modules
|
|
1469
1498
|
extend(*extending_values) if extending_values.any?
|
|
1470
1499
|
|
|
1471
1500
|
self
|
|
@@ -1533,7 +1562,7 @@ module ActiveRecord
|
|
|
1533
1562
|
|
|
1534
1563
|
# Like #annotate, but modifies relation in place.
|
|
1535
1564
|
def annotate!(*args) # :nodoc:
|
|
1536
|
-
self.annotate_values
|
|
1565
|
+
self.annotate_values |= args
|
|
1537
1566
|
self
|
|
1538
1567
|
end
|
|
1539
1568
|
|
|
@@ -1585,14 +1614,14 @@ module ActiveRecord
|
|
|
1585
1614
|
alias :without :excluding
|
|
1586
1615
|
|
|
1587
1616
|
def excluding!(records) # :nodoc:
|
|
1588
|
-
|
|
1589
|
-
self.where_clause +=
|
|
1617
|
+
ids = records.map { |record| record.is_a?(model) ? record.id : record }
|
|
1618
|
+
self.where_clause += build_where_clause(primary_key => ids).invert
|
|
1590
1619
|
self
|
|
1591
1620
|
end
|
|
1592
1621
|
|
|
1593
1622
|
# Returns the Arel object associated with the relation.
|
|
1594
1623
|
def arel(aliases = nil) # :nodoc:
|
|
1595
|
-
@arel ||=
|
|
1624
|
+
@arel ||= build_arel(aliases)
|
|
1596
1625
|
end
|
|
1597
1626
|
|
|
1598
1627
|
def construct_join_dependency(associations, join_type) # :nodoc:
|
|
@@ -1626,7 +1655,7 @@ module ActiveRecord
|
|
|
1626
1655
|
elsif opts.include?("?")
|
|
1627
1656
|
parts = [build_bound_sql_literal(opts, rest)]
|
|
1628
1657
|
else
|
|
1629
|
-
parts = [model.sanitize_sql(
|
|
1658
|
+
parts = [Arel.sql(model.sanitize_sql([opts, *rest]))]
|
|
1630
1659
|
end
|
|
1631
1660
|
when Hash
|
|
1632
1661
|
opts = opts.transform_keys do |key|
|
|
@@ -1653,13 +1682,12 @@ module ActiveRecord
|
|
|
1653
1682
|
end
|
|
1654
1683
|
alias :build_having_clause :build_where_clause
|
|
1655
1684
|
|
|
1656
|
-
def async!
|
|
1685
|
+
def async! # :nodoc:
|
|
1657
1686
|
@async = true
|
|
1658
1687
|
self
|
|
1659
1688
|
end
|
|
1660
1689
|
|
|
1661
|
-
|
|
1662
|
-
def arel_columns(columns)
|
|
1690
|
+
def arel_columns(columns) # :nodoc:
|
|
1663
1691
|
columns.flat_map do |field|
|
|
1664
1692
|
case field
|
|
1665
1693
|
when Symbol, String
|
|
@@ -1747,32 +1775,27 @@ module ActiveRecord
|
|
|
1747
1775
|
raise UnmodifiableRelation if @loaded || @arel
|
|
1748
1776
|
end
|
|
1749
1777
|
|
|
1750
|
-
def build_arel(
|
|
1778
|
+
def build_arel(aliases)
|
|
1751
1779
|
arel = Arel::SelectManager.new(table)
|
|
1752
1780
|
|
|
1753
1781
|
build_joins(arel.join_sources, aliases)
|
|
1754
1782
|
|
|
1755
1783
|
arel.where(where_clause.ast) unless where_clause.empty?
|
|
1756
1784
|
arel.having(having_clause.ast) unless having_clause.empty?
|
|
1757
|
-
arel.take(build_cast_value("LIMIT",
|
|
1785
|
+
arel.take(build_cast_value("LIMIT", limit_value)) if limit_value
|
|
1758
1786
|
arel.skip(build_cast_value("OFFSET", offset_value.to_i)) if offset_value
|
|
1759
|
-
arel.group(*arel_columns(group_values
|
|
1787
|
+
arel.group(*arel_columns(group_values)) unless group_values.empty?
|
|
1760
1788
|
|
|
1761
1789
|
build_order(arel)
|
|
1762
1790
|
build_with(arel)
|
|
1763
1791
|
build_select(arel)
|
|
1764
1792
|
|
|
1765
1793
|
arel.optimizer_hints(*optimizer_hints_values) unless optimizer_hints_values.empty?
|
|
1794
|
+
arel.comment(*annotate_values) unless annotate_values.empty?
|
|
1766
1795
|
arel.distinct(distinct_value)
|
|
1767
1796
|
arel.from(build_from) unless from_clause.empty?
|
|
1768
1797
|
arel.lock(lock_value) if lock_value
|
|
1769
1798
|
|
|
1770
|
-
unless annotate_values.empty?
|
|
1771
|
-
annotates = annotate_values
|
|
1772
|
-
annotates = annotates.uniq if annotates.size > 1
|
|
1773
|
-
arel.comment(*annotates)
|
|
1774
|
-
end
|
|
1775
|
-
|
|
1776
1799
|
arel
|
|
1777
1800
|
end
|
|
1778
1801
|
|
|
@@ -1903,7 +1926,7 @@ module ActiveRecord
|
|
|
1903
1926
|
def build_select(arel)
|
|
1904
1927
|
if select_values.any?
|
|
1905
1928
|
arel.project(*arel_columns(select_values))
|
|
1906
|
-
elsif model.ignored_columns.any? || model.enumerate_columns_in_select_statements
|
|
1929
|
+
elsif model.ignored_columns.any? || model.enumerate_columns_in_select_statements || model.only_columns.any?
|
|
1907
1930
|
arel.project(*model.column_names.map { |field| table[field] })
|
|
1908
1931
|
else
|
|
1909
1932
|
arel.project(table[Arel.star])
|
|
@@ -1928,7 +1951,8 @@ module ActiveRecord
|
|
|
1928
1951
|
|
|
1929
1952
|
def build_with_expression_from_value(value, nested = false)
|
|
1930
1953
|
case value
|
|
1931
|
-
when Arel::Nodes::SqlLiteral
|
|
1954
|
+
when Arel::Nodes::SqlLiteral, Arel::Nodes::BoundSqlLiteral
|
|
1955
|
+
Arel::Nodes::Grouping.new(value)
|
|
1932
1956
|
when ActiveRecord::Relation
|
|
1933
1957
|
if nested
|
|
1934
1958
|
value.arel.ast
|
|
@@ -2001,8 +2025,10 @@ module ActiveRecord
|
|
|
2001
2025
|
yield field
|
|
2002
2026
|
elsif Arel.arel_node?(field)
|
|
2003
2027
|
field
|
|
2028
|
+
elsif is_symbol
|
|
2029
|
+
Arel.sql(model.adapter_class.quote_table_name(field), retryable: true)
|
|
2004
2030
|
else
|
|
2005
|
-
Arel.sql(
|
|
2031
|
+
Arel.sql(field)
|
|
2006
2032
|
end
|
|
2007
2033
|
end
|
|
2008
2034
|
|
|
@@ -2014,9 +2040,15 @@ module ActiveRecord
|
|
|
2014
2040
|
|
|
2015
2041
|
def reverse_sql_order(order_query)
|
|
2016
2042
|
if order_query.empty?
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2043
|
+
if !_reverse_order_columns.empty?
|
|
2044
|
+
return _reverse_order_columns.map { |column| table[column].desc }
|
|
2045
|
+
end
|
|
2046
|
+
|
|
2047
|
+
raise IrreversibleOrderError, <<~MSG.squish
|
|
2048
|
+
Relation has no order values, and #{model} has no order columns to use as a default.
|
|
2049
|
+
Set at least one of `implicit_order_column`, or `primary_key` on the model when no
|
|
2050
|
+
`order `is specified on the relation.
|
|
2051
|
+
MSG
|
|
2020
2052
|
end
|
|
2021
2053
|
|
|
2022
2054
|
order_query.flat_map do |o|
|
|
@@ -2041,6 +2073,13 @@ module ActiveRecord
|
|
|
2041
2073
|
end
|
|
2042
2074
|
end
|
|
2043
2075
|
|
|
2076
|
+
def _reverse_order_columns
|
|
2077
|
+
roc = []
|
|
2078
|
+
roc << model.implicit_order_column if model.implicit_order_column
|
|
2079
|
+
roc << model.primary_key if model.primary_key
|
|
2080
|
+
roc.flatten.uniq.compact
|
|
2081
|
+
end
|
|
2082
|
+
|
|
2044
2083
|
def does_not_support_reverse?(order)
|
|
2045
2084
|
# Account for String subclasses like Arel::Nodes::SqlLiteral that
|
|
2046
2085
|
# override methods like #count.
|
|
@@ -2194,6 +2233,10 @@ module ActiveRecord
|
|
|
2194
2233
|
end
|
|
2195
2234
|
end
|
|
2196
2235
|
|
|
2236
|
+
def qualify_attribute_with_table_name(attr)
|
|
2237
|
+
attr.to_s.include?(".") ? attr : predicate_builder.resolve_arel_attribute(table_name, attr)
|
|
2238
|
+
end
|
|
2239
|
+
|
|
2197
2240
|
# Checks to make sure that the arguments are not blank. Note that if some
|
|
2198
2241
|
# blank-like object were initially passed into the query method, then this
|
|
2199
2242
|
# method will not raise an error.
|
|
@@ -2231,6 +2274,24 @@ module ActiveRecord
|
|
|
2231
2274
|
end
|
|
2232
2275
|
end
|
|
2233
2276
|
|
|
2277
|
+
def cast_values_for_in_order_of(values, type_caster)
|
|
2278
|
+
bad_value = Symbol # use some object that can not be a valid value
|
|
2279
|
+
|
|
2280
|
+
values = values.map do |value|
|
|
2281
|
+
serialized = type_caster.serialize(value) if type_caster.serializable?(value)
|
|
2282
|
+
|
|
2283
|
+
if value.nil?
|
|
2284
|
+
nil
|
|
2285
|
+
elsif !serialized.nil?
|
|
2286
|
+
serialized
|
|
2287
|
+
else
|
|
2288
|
+
bad_value
|
|
2289
|
+
end
|
|
2290
|
+
end
|
|
2291
|
+
|
|
2292
|
+
values.without(bad_value)
|
|
2293
|
+
end
|
|
2294
|
+
|
|
2234
2295
|
def arel_column_aliases_from_hash(fields)
|
|
2235
2296
|
fields.flat_map do |key, columns_aliases|
|
|
2236
2297
|
table_name = key.is_a?(Symbol) ? key.name : key
|
|
@@ -2267,11 +2328,11 @@ module ActiveRecord
|
|
|
2267
2328
|
values = other.values
|
|
2268
2329
|
STRUCTURAL_VALUE_METHODS.reject do |method|
|
|
2269
2330
|
v1, v2 = @values[method], values[method]
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2331
|
+
|
|
2332
|
+
# `and`/`or` are focused to combine where-like clauses, so it relaxes
|
|
2333
|
+
# the difference when other's multi values are uninitialized.
|
|
2334
|
+
next true if v1.is_a?(Array) && v2.nil?
|
|
2335
|
+
|
|
2275
2336
|
v1 == v2
|
|
2276
2337
|
end
|
|
2277
2338
|
end
|
|
@@ -52,18 +52,18 @@ module ActiveRecord
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
# Removes
|
|
55
|
+
# Removes the condition(s) specified in +skips+ from the query.
|
|
56
56
|
#
|
|
57
|
-
# Post.order('id asc').except(:order) #
|
|
58
|
-
# Post.where('id > 10').order('id asc').except(:where) #
|
|
57
|
+
# Post.order('id asc').except(:order) # removes the order condition
|
|
58
|
+
# Post.where('id > 10').order('id asc').except(:where) # removes the where condition but keeps the order
|
|
59
59
|
def except(*skips)
|
|
60
60
|
relation_with values.except(*skips)
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
#
|
|
63
|
+
# Keeps only the condition(s) specified in +onlies+ in the query, removing all others.
|
|
64
64
|
#
|
|
65
|
-
# Post.order('id asc').only(:where) #
|
|
66
|
-
# Post.order('id asc').only(:where, :order) #
|
|
65
|
+
# Post.order('id asc').only(:where) # keeps only the where condition, removes the order
|
|
66
|
+
# Post.order('id asc').only(:where, :order) # keeps only the where and order conditions
|
|
67
67
|
def only(*onlies)
|
|
68
68
|
relation_with values.slice(*onlies)
|
|
69
69
|
end
|
|
@@ -135,10 +135,14 @@ module ActiveRecord
|
|
|
135
135
|
|
|
136
136
|
def extract_attribute(node)
|
|
137
137
|
attr_node = nil
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
|
|
139
|
+
valid_attrs = Arel.fetch_attribute(node) do |attr|
|
|
140
|
+
!attr_node || attr_node == attr # all attr nodes should be the same
|
|
141
|
+
ensure
|
|
140
142
|
attr_node = attr
|
|
141
143
|
end
|
|
144
|
+
return unless valid_attrs # all nested nodes should yield an attribute
|
|
145
|
+
|
|
142
146
|
attr_node
|
|
143
147
|
end
|
|
144
148
|
|
|
@@ -172,11 +176,13 @@ module ActiveRecord
|
|
|
172
176
|
end
|
|
173
177
|
|
|
174
178
|
def except_predicates(columns)
|
|
179
|
+
return predicates if columns.empty?
|
|
180
|
+
|
|
175
181
|
attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
|
|
176
182
|
non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
|
|
177
183
|
|
|
178
184
|
predicates.reject do |node|
|
|
179
|
-
if !non_attrs.empty? && node
|
|
185
|
+
if !non_attrs.empty? && equality_node?(node) && node.left.is_a?(Arel::Predications)
|
|
180
186
|
non_attrs.include?(node.left)
|
|
181
187
|
end || Arel.fetch_attribute(node) do |attr|
|
|
182
188
|
attrs.include?(attr) || columns.include?(attr.name.to_s)
|
|
@@ -188,7 +194,7 @@ module ActiveRecord
|
|
|
188
194
|
non_empty_predicates.map do |node|
|
|
189
195
|
case node
|
|
190
196
|
when Arel::Nodes::SqlLiteral, ::String
|
|
191
|
-
|
|
197
|
+
Arel::Nodes::Grouping.new(node)
|
|
192
198
|
else node
|
|
193
199
|
end
|
|
194
200
|
end
|
|
@@ -199,13 +205,6 @@ module ActiveRecord
|
|
|
199
205
|
predicates - ARRAY_WITH_EMPTY_STRING
|
|
200
206
|
end
|
|
201
207
|
|
|
202
|
-
def wrap_sql_literal(node)
|
|
203
|
-
if ::String === node
|
|
204
|
-
node = Arel.sql(node)
|
|
205
|
-
end
|
|
206
|
-
Arel::Nodes::Grouping.new(node)
|
|
207
|
-
end
|
|
208
|
-
|
|
209
208
|
def extract_node_value(node)
|
|
210
209
|
if node.respond_to?(:value_before_type_cast)
|
|
211
210
|
node.value_before_type_cast
|