activerecord 7.2.3 → 8.0.0.beta1
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 +192 -1261
- data/README.rdoc +2 -2
- data/lib/active_record/associations/alias_tracker.rb +4 -6
- data/lib/active_record/associations/association.rb +25 -5
- data/lib/active_record/associations/belongs_to_association.rb +2 -18
- data/lib/active_record/associations/builder/association.rb +7 -6
- data/lib/active_record/associations/collection_association.rb +4 -4
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +4 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
- 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 +50 -32
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods.rb +19 -24
- data/lib/active_record/attributes.rb +26 -37
- data/lib/active_record/autosave_association.rb +81 -49
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +1 -1
- 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 +31 -75
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +14 -19
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +2 -6
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +27 -9
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +27 -57
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +28 -58
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -15
- 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 +2 -16
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +12 -14
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +51 -9
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +44 -101
- 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/quoting.rb +0 -13
- 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 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +60 -22
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -18
- data/lib/active_record/connection_handling.rb +29 -11
- data/lib/active_record/core.rb +15 -60
- data/lib/active_record/counter_cache.rb +1 -1
- data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -3
- data/lib/active_record/delegated_type.rb +18 -18
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +5 -5
- data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
- data/lib/active_record/encryption/encryptor.rb +35 -29
- 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 +12 -13
- data/lib/active_record/errors.rb +16 -8
- data/lib/active_record/fixture_set/table_row.rb +2 -19
- data/lib/active_record/fixtures.rb +0 -1
- data/lib/active_record/future_result.rb +14 -10
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/insert_all.rb +1 -1
- data/lib/active_record/marshalling.rb +1 -4
- data/lib/active_record/migration/command_recorder.rb +22 -5
- data/lib/active_record/migration/compatibility.rb +5 -2
- data/lib/active_record/migration.rb +36 -35
- data/lib/active_record/model_schema.rb +1 -1
- data/lib/active_record/nested_attributes.rb +4 -6
- data/lib/active_record/persistence.rb +128 -130
- data/lib/active_record/query_cache.rb +5 -4
- data/lib/active_record/query_logs.rb +98 -44
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +10 -10
- data/lib/active_record/railtie.rb +5 -6
- data/lib/active_record/railties/databases.rake +1 -2
- data/lib/active_record/reflection.rb +9 -7
- 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 +55 -55
- data/lib/active_record/relation/delegation.rb +25 -14
- data/lib/active_record/relation/finder_methods.rb +31 -32
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +0 -2
- 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 +5 -0
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +90 -91
- data/lib/active_record/relation/record_fetch_warning.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +2 -8
- data/lib/active_record/relation.rb +77 -76
- data/lib/active_record/result.rb +68 -7
- data/lib/active_record/sanitization.rb +7 -6
- data/lib/active_record/schema_dumper.rb +16 -29
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +6 -7
- data/lib/active_record/statement_cache.rb +12 -12
- data/lib/active_record/store.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +24 -15
- data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
- data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
- data/lib/active_record/test_fixtures.rb +12 -0
- data/lib/active_record/testing/query_assertions.rb +2 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transactions.rb +1 -3
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +16 -1
- data/lib/arel/collectors/bind.rb +1 -1
- data/lib/arel/crud.rb +0 -2
- data/lib/arel/delete_manager.rb +0 -5
- data/lib/arel/nodes/delete_statement.rb +2 -4
- data/lib/arel/nodes/update_statement.rb +2 -4
- data/lib/arel/select_manager.rb +2 -6
- data/lib/arel/update_manager.rb +0 -5
- data/lib/arel/visitors/dot.rb +0 -2
- data/lib/arel/visitors/sqlite.rb +0 -25
- data/lib/arel/visitors/to_sql.rb +1 -3
- metadata +14 -11
|
@@ -92,10 +92,11 @@ module ActiveRecord
|
|
|
92
92
|
@scope.joins!(association)
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
+
association_conditions = Array(reflection.association_primary_key).index_with(nil)
|
|
95
96
|
if reflection.options[:class_name]
|
|
96
|
-
self.not(association =>
|
|
97
|
+
self.not(association => association_conditions)
|
|
97
98
|
else
|
|
98
|
-
self.not(reflection.table_name =>
|
|
99
|
+
self.not(reflection.table_name => association_conditions)
|
|
99
100
|
end
|
|
100
101
|
end
|
|
101
102
|
|
|
@@ -124,10 +125,11 @@ module ActiveRecord
|
|
|
124
125
|
associations.each do |association|
|
|
125
126
|
reflection = scope_association_reflection(association)
|
|
126
127
|
@scope.left_outer_joins!(association)
|
|
128
|
+
association_conditions = Array(reflection.association_primary_key).index_with(nil)
|
|
127
129
|
if reflection.options[:class_name]
|
|
128
|
-
@scope.where!(association =>
|
|
130
|
+
@scope.where!(association => association_conditions)
|
|
129
131
|
else
|
|
130
|
-
@scope.where!(reflection.table_name =>
|
|
132
|
+
@scope.where!(reflection.table_name => association_conditions)
|
|
131
133
|
end
|
|
132
134
|
end
|
|
133
135
|
|
|
@@ -136,9 +138,10 @@ module ActiveRecord
|
|
|
136
138
|
|
|
137
139
|
private
|
|
138
140
|
def scope_association_reflection(association)
|
|
139
|
-
|
|
141
|
+
model = @scope.model
|
|
142
|
+
reflection = model._reflect_on_association(association)
|
|
140
143
|
unless reflection
|
|
141
|
-
raise ArgumentError.new("An association named `:#{association}` does not exist on the model `#{
|
|
144
|
+
raise ArgumentError.new("An association named `:#{association}` does not exist on the model `#{model.name}`.")
|
|
142
145
|
end
|
|
143
146
|
reflection
|
|
144
147
|
end
|
|
@@ -254,6 +257,10 @@ module ActiveRecord
|
|
|
254
257
|
self
|
|
255
258
|
end
|
|
256
259
|
|
|
260
|
+
def all # :nodoc:
|
|
261
|
+
spawn
|
|
262
|
+
end
|
|
263
|
+
|
|
257
264
|
# Specify associations +args+ to be eager loaded using a <tt>LEFT OUTER JOIN</tt>.
|
|
258
265
|
# Performs a single query joining all specified associations. For example:
|
|
259
266
|
#
|
|
@@ -491,8 +498,7 @@ module ActiveRecord
|
|
|
491
498
|
|
|
492
499
|
# Like #with, but modifies relation in place.
|
|
493
500
|
def with!(*args) # :nodoc:
|
|
494
|
-
|
|
495
|
-
self.with_values |= args
|
|
501
|
+
self.with_values += args
|
|
496
502
|
self
|
|
497
503
|
end
|
|
498
504
|
|
|
@@ -503,7 +509,7 @@ module ActiveRecord
|
|
|
503
509
|
# # WITH post_and_replies AS (
|
|
504
510
|
# # (SELECT * FROM posts WHERE id = 42)
|
|
505
511
|
# # UNION ALL
|
|
506
|
-
# # (SELECT * FROM posts JOIN
|
|
512
|
+
# # (SELECT * FROM posts JOIN posts_and_replies ON posts.in_reply_to_id = posts_and_replies.id)
|
|
507
513
|
# # )
|
|
508
514
|
# # SELECT * FROM posts
|
|
509
515
|
#
|
|
@@ -515,8 +521,7 @@ module ActiveRecord
|
|
|
515
521
|
|
|
516
522
|
# Like #with_recursive but modifies the relation in place.
|
|
517
523
|
def with_recursive!(*args) # :nodoc:
|
|
518
|
-
|
|
519
|
-
self.with_values |= args
|
|
524
|
+
self.with_values += args
|
|
520
525
|
@with_is_recursive = true
|
|
521
526
|
self
|
|
522
527
|
end
|
|
@@ -698,26 +703,39 @@ module ActiveRecord
|
|
|
698
703
|
# # WHEN "conversations"."status" = 0 THEN 3
|
|
699
704
|
# # END ASC
|
|
700
705
|
#
|
|
701
|
-
|
|
702
|
-
|
|
706
|
+
# +filter+ can be set to +false+ to include all results instead of only the ones specified in +values+.
|
|
707
|
+
#
|
|
708
|
+
# Conversation.in_order_of(:status, [:archived, :active], filter: false)
|
|
709
|
+
# # SELECT "conversations".* FROM "conversations"
|
|
710
|
+
# # ORDER BY CASE
|
|
711
|
+
# # WHEN "conversations"."status" = 1 THEN 1
|
|
712
|
+
# # WHEN "conversations"."status" = 0 THEN 2
|
|
713
|
+
# # ELSE 3
|
|
714
|
+
# # END ASC
|
|
715
|
+
def in_order_of(column, values, filter: true)
|
|
716
|
+
model.disallow_raw_sql!([column], permit: model.adapter_class.column_name_with_order_matcher)
|
|
703
717
|
return spawn.none! if values.empty?
|
|
704
718
|
|
|
705
719
|
references = column_references([column])
|
|
706
720
|
self.references_values |= references unless references.empty?
|
|
707
721
|
|
|
708
|
-
values = values.map { |value| type_caster.type_cast_for_database(column, value) }
|
|
722
|
+
values = values.map { |value| model.type_caster.type_cast_for_database(column, value) }
|
|
709
723
|
arel_column = column.is_a?(Arel::Nodes::SqlLiteral) ? column : order_column(column.to_s)
|
|
710
724
|
|
|
711
|
-
|
|
712
|
-
if values.include?(nil)
|
|
713
|
-
arel_column.in(values.compact).or(arel_column.eq(nil))
|
|
714
|
-
else
|
|
715
|
-
arel_column.in(values)
|
|
716
|
-
end
|
|
725
|
+
scope = spawn.order!(build_case_for_value_position(arel_column, values, filter: filter))
|
|
717
726
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
727
|
+
if filter
|
|
728
|
+
where_clause =
|
|
729
|
+
if values.include?(nil)
|
|
730
|
+
arel_column.in(values.compact).or(arel_column.eq(nil))
|
|
731
|
+
else
|
|
732
|
+
arel_column.in(values)
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
scope = scope.where!(where_clause)
|
|
736
|
+
end
|
|
737
|
+
|
|
738
|
+
scope
|
|
721
739
|
end
|
|
722
740
|
|
|
723
741
|
# Replaces any existing order defined on the relation with the specified order.
|
|
@@ -1279,13 +1297,13 @@ module ActiveRecord
|
|
|
1279
1297
|
#
|
|
1280
1298
|
# users = User.readonly
|
|
1281
1299
|
# users.first.save
|
|
1282
|
-
#
|
|
1300
|
+
# => ActiveRecord::ReadOnlyRecord: User is marked as readonly
|
|
1283
1301
|
#
|
|
1284
1302
|
# To make a readonly relation writable, pass +false+.
|
|
1285
1303
|
#
|
|
1286
1304
|
# users.readonly(false)
|
|
1287
1305
|
# users.first.save
|
|
1288
|
-
#
|
|
1306
|
+
# => true
|
|
1289
1307
|
def readonly(value = true)
|
|
1290
1308
|
spawn.readonly!(value)
|
|
1291
1309
|
end
|
|
@@ -1300,7 +1318,7 @@ module ActiveRecord
|
|
|
1300
1318
|
#
|
|
1301
1319
|
# user = User.strict_loading.first
|
|
1302
1320
|
# user.comments.to_a
|
|
1303
|
-
#
|
|
1321
|
+
# => ActiveRecord::StrictLoadingViolationError
|
|
1304
1322
|
def strict_loading(value = true)
|
|
1305
1323
|
spawn.strict_loading!(value)
|
|
1306
1324
|
end
|
|
@@ -1556,8 +1574,8 @@ module ActiveRecord
|
|
|
1556
1574
|
records.flatten!(1)
|
|
1557
1575
|
records.compact!
|
|
1558
1576
|
|
|
1559
|
-
unless records.all?(
|
|
1560
|
-
raise ArgumentError, "You must only pass a single or collection of #{
|
|
1577
|
+
unless records.all?(model) && relations.all? { |relation| relation.model == model }
|
|
1578
|
+
raise ArgumentError, "You must only pass a single or collection of #{model.name} objects to ##{__callee__}."
|
|
1561
1579
|
end
|
|
1562
1580
|
|
|
1563
1581
|
spawn.excluding!(records + relations.flat_map(&:ids))
|
|
@@ -1577,7 +1595,7 @@ module ActiveRecord
|
|
|
1577
1595
|
|
|
1578
1596
|
def construct_join_dependency(associations, join_type) # :nodoc:
|
|
1579
1597
|
ActiveRecord::Associations::JoinDependency.new(
|
|
1580
|
-
|
|
1598
|
+
model, table, associations, join_type
|
|
1581
1599
|
)
|
|
1582
1600
|
end
|
|
1583
1601
|
|
|
@@ -1606,15 +1624,15 @@ module ActiveRecord
|
|
|
1606
1624
|
elsif opts.include?("?")
|
|
1607
1625
|
parts = [build_bound_sql_literal(opts, rest)]
|
|
1608
1626
|
else
|
|
1609
|
-
parts = [
|
|
1627
|
+
parts = [model.sanitize_sql(rest.empty? ? opts : [opts, *rest])]
|
|
1610
1628
|
end
|
|
1611
1629
|
when Hash
|
|
1612
1630
|
opts = opts.transform_keys do |key|
|
|
1613
1631
|
if key.is_a?(Array)
|
|
1614
|
-
key.map { |k|
|
|
1632
|
+
key.map { |k| model.attribute_aliases[k.to_s] || k.to_s }
|
|
1615
1633
|
else
|
|
1616
1634
|
key = key.to_s
|
|
1617
|
-
|
|
1635
|
+
model.attribute_aliases[key] || key
|
|
1618
1636
|
end
|
|
1619
1637
|
end
|
|
1620
1638
|
references = PredicateBuilder.references(opts)
|
|
@@ -1638,26 +1656,6 @@ module ActiveRecord
|
|
|
1638
1656
|
self
|
|
1639
1657
|
end
|
|
1640
1658
|
|
|
1641
|
-
protected
|
|
1642
|
-
def arel_columns(columns)
|
|
1643
|
-
columns.flat_map do |field|
|
|
1644
|
-
case field
|
|
1645
|
-
when Symbol
|
|
1646
|
-
arel_column(field.to_s) do |attr_name|
|
|
1647
|
-
adapter_class.quote_table_name(attr_name)
|
|
1648
|
-
end
|
|
1649
|
-
when String
|
|
1650
|
-
arel_column(field, &:itself)
|
|
1651
|
-
when Proc
|
|
1652
|
-
field.call
|
|
1653
|
-
when Hash
|
|
1654
|
-
arel_columns_from_hash(field)
|
|
1655
|
-
else
|
|
1656
|
-
field
|
|
1657
|
-
end
|
|
1658
|
-
end
|
|
1659
|
-
end
|
|
1660
|
-
|
|
1661
1659
|
private
|
|
1662
1660
|
def async
|
|
1663
1661
|
spawn.async!
|
|
@@ -1830,7 +1828,7 @@ module ActiveRecord
|
|
|
1830
1828
|
|
|
1831
1829
|
joins = joins_values.dup
|
|
1832
1830
|
if joins.last.is_a?(ActiveRecord::Associations::JoinDependency)
|
|
1833
|
-
stashed_eager_load = joins.pop if joins.last.base_klass ==
|
|
1831
|
+
stashed_eager_load = joins.pop if joins.last.base_klass == model
|
|
1834
1832
|
end
|
|
1835
1833
|
|
|
1836
1834
|
joins.each_with_index do |join, i|
|
|
@@ -1887,8 +1885,8 @@ module ActiveRecord
|
|
|
1887
1885
|
def build_select(arel)
|
|
1888
1886
|
if select_values.any?
|
|
1889
1887
|
arel.project(*arel_columns(select_values))
|
|
1890
|
-
elsif
|
|
1891
|
-
arel.project(*
|
|
1888
|
+
elsif model.ignored_columns.any? || model.enumerate_columns_in_select_statements
|
|
1889
|
+
arel.project(*model.column_names.map { |field| table[field] })
|
|
1892
1890
|
else
|
|
1893
1891
|
arel.project(table[Arel.star])
|
|
1894
1892
|
end
|
|
@@ -1898,6 +1896,8 @@ module ActiveRecord
|
|
|
1898
1896
|
return if with_values.empty?
|
|
1899
1897
|
|
|
1900
1898
|
with_statements = with_values.map do |with_value|
|
|
1899
|
+
raise ArgumentError, "Unsupported argument type: #{with_value} #{with_value.class}" unless with_value.is_a?(Hash)
|
|
1900
|
+
|
|
1901
1901
|
build_with_value_from_hash(with_value)
|
|
1902
1902
|
end
|
|
1903
1903
|
|
|
@@ -1910,26 +1910,12 @@ module ActiveRecord
|
|
|
1910
1910
|
end
|
|
1911
1911
|
end
|
|
1912
1912
|
|
|
1913
|
-
def build_with_expression_from_value(value
|
|
1913
|
+
def build_with_expression_from_value(value)
|
|
1914
1914
|
case value
|
|
1915
1915
|
when Arel::Nodes::SqlLiteral then Arel::Nodes::Grouping.new(value)
|
|
1916
|
-
when ActiveRecord::Relation
|
|
1917
|
-
if nested
|
|
1918
|
-
value.arel.ast
|
|
1919
|
-
else
|
|
1920
|
-
value.arel
|
|
1921
|
-
end
|
|
1916
|
+
when ActiveRecord::Relation then value.arel
|
|
1922
1917
|
when Arel::SelectManager then value
|
|
1923
|
-
when Array
|
|
1924
|
-
return build_with_expression_from_value(value.first, false) if value.size == 1
|
|
1925
|
-
|
|
1926
|
-
parts = value.map do |query|
|
|
1927
|
-
build_with_expression_from_value(query, true)
|
|
1928
|
-
end
|
|
1929
|
-
|
|
1930
|
-
parts.reduce do |result, value|
|
|
1931
|
-
Arel::Nodes::UnionAll.new(result, value)
|
|
1932
|
-
end
|
|
1918
|
+
when Array then value.map { |q| build_with_expression_from_value(q) }.reduce { |result, value| result.union(:all, value) }
|
|
1933
1919
|
else
|
|
1934
1920
|
raise ArgumentError, "Unsupported argument type: `#{value}` #{value.class}"
|
|
1935
1921
|
end
|
|
@@ -1939,18 +1925,37 @@ module ActiveRecord
|
|
|
1939
1925
|
with_table = Arel::Table.new(name)
|
|
1940
1926
|
|
|
1941
1927
|
table.join(with_table, kind).on(
|
|
1942
|
-
with_table[
|
|
1928
|
+
with_table[model.model_name.to_s.foreign_key].eq(table[model.primary_key])
|
|
1943
1929
|
).join_sources.first
|
|
1944
1930
|
end
|
|
1945
1931
|
|
|
1932
|
+
def arel_columns(columns)
|
|
1933
|
+
columns.flat_map do |field|
|
|
1934
|
+
case field
|
|
1935
|
+
when Symbol
|
|
1936
|
+
arel_column(field.to_s) do |attr_name|
|
|
1937
|
+
model.adapter_class.quote_table_name(attr_name)
|
|
1938
|
+
end
|
|
1939
|
+
when String
|
|
1940
|
+
arel_column(field, &:itself)
|
|
1941
|
+
when Proc
|
|
1942
|
+
field.call
|
|
1943
|
+
when Hash
|
|
1944
|
+
arel_columns_from_hash(field)
|
|
1945
|
+
else
|
|
1946
|
+
field
|
|
1947
|
+
end
|
|
1948
|
+
end
|
|
1949
|
+
end
|
|
1950
|
+
|
|
1946
1951
|
def arel_column(field)
|
|
1947
|
-
field =
|
|
1952
|
+
field = model.attribute_aliases[field] || field
|
|
1948
1953
|
from = from_clause.name || from_clause.value
|
|
1949
1954
|
|
|
1950
|
-
if
|
|
1955
|
+
if model.columns_hash.key?(field) && (!from || table_name_matches?(from))
|
|
1951
1956
|
table[field]
|
|
1952
|
-
elsif /\A
|
|
1953
|
-
|
|
1957
|
+
elsif field.match?(/\A\w+\.\w+\z/)
|
|
1958
|
+
table, column = field.split(".")
|
|
1954
1959
|
predicate_builder.resolve_arel_attribute(table, column) do
|
|
1955
1960
|
lookup_table_klass_from_join_dependencies(table)
|
|
1956
1961
|
end
|
|
@@ -1961,7 +1966,7 @@ module ActiveRecord
|
|
|
1961
1966
|
|
|
1962
1967
|
def table_name_matches?(from)
|
|
1963
1968
|
table_name = Regexp.escape(table.name)
|
|
1964
|
-
quoted_table_name = Regexp.escape(adapter_class.quote_table_name(table.name))
|
|
1969
|
+
quoted_table_name = Regexp.escape(model.adapter_class.quote_table_name(table.name))
|
|
1965
1970
|
/(?:\A|(?<!FROM)\s)(?:\b#{table_name}\b|#{quoted_table_name})(?!\.)/i.match?(from.to_s)
|
|
1966
1971
|
end
|
|
1967
1972
|
|
|
@@ -2032,7 +2037,7 @@ module ActiveRecord
|
|
|
2032
2037
|
end
|
|
2033
2038
|
|
|
2034
2039
|
def preprocess_order_args(order_args)
|
|
2035
|
-
|
|
2040
|
+
model.disallow_raw_sql!(
|
|
2036
2041
|
flattened_args(order_args),
|
|
2037
2042
|
permit: model.adapter_class.column_name_with_order_matcher
|
|
2038
2043
|
)
|
|
@@ -2070,7 +2075,7 @@ module ActiveRecord
|
|
|
2070
2075
|
|
|
2071
2076
|
def sanitize_order_arguments(order_args)
|
|
2072
2077
|
order_args.map! do |arg|
|
|
2073
|
-
|
|
2078
|
+
model.sanitize_sql_for_order(arg)
|
|
2074
2079
|
end
|
|
2075
2080
|
end
|
|
2076
2081
|
|
|
@@ -2096,7 +2101,7 @@ module ActiveRecord
|
|
|
2096
2101
|
arg.expr.relation.name
|
|
2097
2102
|
end
|
|
2098
2103
|
end
|
|
2099
|
-
end.
|
|
2104
|
+
end.compact
|
|
2100
2105
|
end
|
|
2101
2106
|
|
|
2102
2107
|
def extract_table_name_from(string)
|
|
@@ -2108,17 +2113,18 @@ module ActiveRecord
|
|
|
2108
2113
|
if attr_name == "count" && !group_values.empty?
|
|
2109
2114
|
table[attr_name]
|
|
2110
2115
|
else
|
|
2111
|
-
Arel.sql(adapter_class.quote_table_name(attr_name), retryable: true)
|
|
2116
|
+
Arel.sql(model.adapter_class.quote_table_name(attr_name), retryable: true)
|
|
2112
2117
|
end
|
|
2113
2118
|
end
|
|
2114
2119
|
end
|
|
2115
2120
|
|
|
2116
|
-
def build_case_for_value_position(column, values)
|
|
2121
|
+
def build_case_for_value_position(column, values, filter: true)
|
|
2117
2122
|
node = Arel::Nodes::Case.new
|
|
2118
2123
|
values.each.with_index(1) do |value, order|
|
|
2119
2124
|
node.when(column.eq(value)).then(order)
|
|
2120
2125
|
end
|
|
2121
2126
|
|
|
2127
|
+
node = node.else(values.length + 1) unless filter
|
|
2122
2128
|
Arel::Nodes::Ascending.new(node)
|
|
2123
2129
|
end
|
|
2124
2130
|
|
|
@@ -2202,19 +2208,12 @@ module ActiveRecord
|
|
|
2202
2208
|
end
|
|
2203
2209
|
when String, Symbol
|
|
2204
2210
|
arel_column(key.to_s) do
|
|
2205
|
-
predicate_builder.resolve_arel_attribute(
|
|
2211
|
+
predicate_builder.resolve_arel_attribute(model.table_name, key.to_s)
|
|
2206
2212
|
end.as(columns_aliases.to_s)
|
|
2207
2213
|
end
|
|
2208
2214
|
end
|
|
2209
2215
|
end
|
|
2210
2216
|
|
|
2211
|
-
def process_with_args(args)
|
|
2212
|
-
args.flat_map do |arg|
|
|
2213
|
-
raise ArgumentError, "Unsupported argument type: #{arg} #{arg.class}" unless arg.is_a?(Hash)
|
|
2214
|
-
arg.map { |k, v| { k => v } }
|
|
2215
|
-
end
|
|
2216
|
-
end
|
|
2217
|
-
|
|
2218
2217
|
STRUCTURAL_VALUE_METHODS = (
|
|
2219
2218
|
Relation::VALUE_METHODS -
|
|
2220
2219
|
[:extending, :where, :having, :unscope, :references, :annotate, :optimizer_hints]
|
|
@@ -20,9 +20,9 @@ module ActiveRecord
|
|
|
20
20
|
QueryRegistry.reset
|
|
21
21
|
|
|
22
22
|
super.tap do |records|
|
|
23
|
-
if logger && ActiveRecord.warn_on_records_fetched_greater_than
|
|
23
|
+
if model.logger && ActiveRecord.warn_on_records_fetched_greater_than
|
|
24
24
|
if records.length > ActiveRecord.warn_on_records_fetched_greater_than
|
|
25
|
-
logger.warn "Query fetched #{records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
|
|
25
|
+
model.logger.warn "Query fetched #{records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
end
|
|
@@ -7,7 +7,7 @@ require "active_record/relation/merger"
|
|
|
7
7
|
module ActiveRecord
|
|
8
8
|
module SpawnMethods
|
|
9
9
|
def spawn # :nodoc:
|
|
10
|
-
already_in_scope?(
|
|
10
|
+
already_in_scope?(model.scope_registry) ? model.all : clone
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
# Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
|
|
@@ -135,14 +135,10 @@ module ActiveRecord
|
|
|
135
135
|
|
|
136
136
|
def extract_attribute(node)
|
|
137
137
|
attr_node = nil
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
!attr_node || attr_node == attr # all attr nodes should be the same
|
|
141
|
-
ensure
|
|
138
|
+
Arel.fetch_attribute(node) do |attr|
|
|
139
|
+
return if attr_node&.!= attr # all attr nodes should be the same
|
|
142
140
|
attr_node = attr
|
|
143
141
|
end
|
|
144
|
-
return unless valid_attrs # all nested nodes should yield an attribute
|
|
145
|
-
|
|
146
142
|
attr_node
|
|
147
143
|
end
|
|
148
144
|
|
|
@@ -176,8 +172,6 @@ module ActiveRecord
|
|
|
176
172
|
end
|
|
177
173
|
|
|
178
174
|
def except_predicates(columns)
|
|
179
|
-
return predicates if columns.empty?
|
|
180
|
-
|
|
181
175
|
attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
|
|
182
176
|
non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
|
|
183
177
|
|