activerecord 7.2.2 → 8.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +173 -920
- data/README.rdoc +1 -1
- data/lib/active_record/associations/association.rb +25 -5
- data/lib/active_record/associations/builder/association.rb +7 -6
- data/lib/active_record/associations/collection_association.rb +10 -8
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +4 -9
- 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/autosave_association.rb +69 -27
- 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 +0 -27
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +27 -6
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +24 -25
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +23 -45
- data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -45
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +42 -98
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -8
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +50 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +41 -93
- data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +55 -12
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +0 -17
- data/lib/active_record/connection_handling.rb +22 -0
- data/lib/active_record/core.rb +7 -32
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +4 -4
- data/lib/active_record/encryption/encrypted_attribute_type.rb +10 -1
- data/lib/active_record/encryption/encryptor.rb +15 -8
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +8 -1
- data/lib/active_record/errors.rb +13 -5
- 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 +35 -33
- 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 -40
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +6 -6
- data/lib/active_record/railtie.rb +3 -4
- 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 +25 -20
- data/lib/active_record/relation/delegation.rb +25 -14
- data/lib/active_record/relation/finder_methods.rb +18 -18
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +5 -0
- data/lib/active_record/relation/query_methods.rb +81 -75
- 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.rb +72 -61
- data/lib/active_record/result.rb +68 -7
- data/lib/active_record/sanitization.rb +7 -6
- data/lib/active_record/schema_dumper.rb +5 -0
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/statement_cache.rb +12 -12
- data/lib/active_record/store.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +24 -15
- data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
- data/lib/active_record/test_fixtures.rb +12 -0
- data/lib/active_record/testing/query_assertions.rb +2 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +15 -0
- data/lib/arel/collectors/bind.rb +1 -1
- data/lib/arel/visitors/sqlite.rb +0 -25
- metadata +10 -10
@@ -145,10 +145,10 @@ module ActiveRecord
|
|
145
145
|
|
146
146
|
if found.nil?
|
147
147
|
raise_record_not_found_exception!
|
148
|
-
elsif undesired.
|
149
|
-
raise ActiveRecord::SoleRecordExceeded.new(self)
|
150
|
-
else
|
148
|
+
elsif undesired.nil?
|
151
149
|
found
|
150
|
+
else
|
151
|
+
raise ActiveRecord::SoleRecordExceeded.new(model)
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
@@ -376,7 +376,7 @@ module ActiveRecord
|
|
376
376
|
|
377
377
|
skip_query_cache_if_necessary do
|
378
378
|
with_connection do |c|
|
379
|
-
c.select_rows(relation.arel, "#{name} Exists?").size == 1
|
379
|
+
c.select_rows(relation.arel, "#{model.name} Exists?").size == 1
|
380
380
|
end
|
381
381
|
end
|
382
382
|
end
|
@@ -389,7 +389,7 @@ module ActiveRecord
|
|
389
389
|
def include?(record)
|
390
390
|
# The existing implementation relies on receiving an Active Record instance as the input parameter named record.
|
391
391
|
# Any non-Active Record object passed to this implementation is guaranteed to return `false`.
|
392
|
-
return false unless record.is_a?(
|
392
|
+
return false unless record.is_a?(model)
|
393
393
|
|
394
394
|
if loaded? || offset_value || limit_value || having_clause.any?
|
395
395
|
records.include?(record)
|
@@ -415,9 +415,9 @@ module ActiveRecord
|
|
415
415
|
# the expected number of results should be provided in the +expected_size+
|
416
416
|
# argument.
|
417
417
|
def raise_record_not_found_exception!(ids = nil, result_size = nil, expected_size = nil, key = primary_key, not_found_ids = nil) # :nodoc:
|
418
|
-
conditions = " [#{arel.where_sql(
|
418
|
+
conditions = " [#{arel.where_sql(model)}]" unless where_clause.empty?
|
419
419
|
|
420
|
-
name =
|
420
|
+
name = model.name
|
421
421
|
|
422
422
|
if ids.nil?
|
423
423
|
error = +"Couldn't find #{name}"
|
@@ -471,7 +471,7 @@ module ActiveRecord
|
|
471
471
|
)
|
472
472
|
)
|
473
473
|
relation = skip_query_cache_if_necessary do
|
474
|
-
|
474
|
+
model.with_connection do |c|
|
475
475
|
c.distinct_relation_for_primary_key(relation)
|
476
476
|
end
|
477
477
|
end
|
@@ -489,9 +489,9 @@ module ActiveRecord
|
|
489
489
|
end
|
490
490
|
|
491
491
|
def find_with_ids(*ids)
|
492
|
-
raise UnknownPrimaryKey.new(
|
492
|
+
raise UnknownPrimaryKey.new(model) if primary_key.nil?
|
493
493
|
|
494
|
-
expects_array = if
|
494
|
+
expects_array = if model.composite_primary_key?
|
495
495
|
ids.first.first.is_a?(Array)
|
496
496
|
else
|
497
497
|
ids.first.is_a?(Array)
|
@@ -503,7 +503,7 @@ module ActiveRecord
|
|
503
503
|
|
504
504
|
ids = ids.compact.uniq
|
505
505
|
|
506
|
-
model_name =
|
506
|
+
model_name = model.name
|
507
507
|
|
508
508
|
case ids.size
|
509
509
|
when 0
|
@@ -525,7 +525,7 @@ module ActiveRecord
|
|
525
525
|
MSG
|
526
526
|
end
|
527
527
|
|
528
|
-
relation = if
|
528
|
+
relation = if model.composite_primary_key?
|
529
529
|
where(primary_key.zip(id).to_h)
|
530
530
|
else
|
531
531
|
where(primary_key => id)
|
@@ -573,7 +573,7 @@ module ActiveRecord
|
|
573
573
|
result = relation.records
|
574
574
|
|
575
575
|
if result.size == ids.size
|
576
|
-
result.in_order_of(:id, ids.map { |id|
|
576
|
+
result.in_order_of(:id, ids.map { |id| model.type_for_attribute(primary_key).cast(id) })
|
577
577
|
else
|
578
578
|
raise_record_not_found_exception!(ids, result.size, ids.size)
|
579
579
|
end
|
@@ -638,7 +638,7 @@ module ActiveRecord
|
|
638
638
|
end
|
639
639
|
|
640
640
|
def ordered_relation
|
641
|
-
if order_values.empty? && (implicit_order_column || !query_constraints_list.nil? || primary_key)
|
641
|
+
if order_values.empty? && (model.implicit_order_column || !model.query_constraints_list.nil? || primary_key)
|
642
642
|
order(_order_columns.map { |column| table[column].asc })
|
643
643
|
else
|
644
644
|
self
|
@@ -648,11 +648,11 @@ module ActiveRecord
|
|
648
648
|
def _order_columns
|
649
649
|
oc = []
|
650
650
|
|
651
|
-
oc << implicit_order_column if implicit_order_column
|
652
|
-
oc << query_constraints_list if query_constraints_list
|
651
|
+
oc << model.implicit_order_column if model.implicit_order_column
|
652
|
+
oc << model.query_constraints_list if model.query_constraints_list
|
653
653
|
|
654
|
-
if primary_key && query_constraints_list.nil?
|
655
|
-
oc << primary_key
|
654
|
+
if model.primary_key && model.query_constraints_list.nil?
|
655
|
+
oc << model.primary_key
|
656
656
|
end
|
657
657
|
|
658
658
|
oc.flatten.uniq.compact
|
@@ -24,7 +24,7 @@ module ActiveRecord
|
|
24
24
|
# the values.
|
25
25
|
def other
|
26
26
|
other = Relation.create(
|
27
|
-
relation.
|
27
|
+
relation.model,
|
28
28
|
table: relation.table,
|
29
29
|
predicate_builder: relation.predicate_builder
|
30
30
|
)
|
@@ -84,7 +84,7 @@ module ActiveRecord
|
|
84
84
|
def merge_select_values
|
85
85
|
return if other.select_values.empty?
|
86
86
|
|
87
|
-
if other.
|
87
|
+
if other.model == relation.model
|
88
88
|
relation.select_values |= other.select_values
|
89
89
|
else
|
90
90
|
relation.select_values |= other.instance_eval do
|
@@ -96,12 +96,12 @@ module ActiveRecord
|
|
96
96
|
def merge_preloads
|
97
97
|
return if other.preload_values.empty? && other.includes_values.empty?
|
98
98
|
|
99
|
-
if other.
|
99
|
+
if other.model == relation.model
|
100
100
|
relation.preload_values |= other.preload_values unless other.preload_values.empty?
|
101
101
|
relation.includes_values |= other.includes_values unless other.includes_values.empty?
|
102
102
|
else
|
103
|
-
reflection = relation.
|
104
|
-
r.class_name == other.
|
103
|
+
reflection = relation.model.reflect_on_all_associations.find do |r|
|
104
|
+
r.class_name == other.model.name
|
105
105
|
end || return
|
106
106
|
|
107
107
|
unless other.preload_values.empty?
|
@@ -117,7 +117,7 @@ module ActiveRecord
|
|
117
117
|
def merge_joins
|
118
118
|
return if other.joins_values.empty?
|
119
119
|
|
120
|
-
if other.
|
120
|
+
if other.model == relation.model
|
121
121
|
relation.joins_values |= other.joins_values
|
122
122
|
else
|
123
123
|
associations, others = other.joins_values.partition do |join|
|
@@ -136,7 +136,7 @@ module ActiveRecord
|
|
136
136
|
def merge_outer_joins
|
137
137
|
return if other.left_outer_joins_values.empty?
|
138
138
|
|
139
|
-
if other.
|
139
|
+
if other.model == relation.model
|
140
140
|
relation.left_outer_joins_values |= other.left_outer_joins_values
|
141
141
|
else
|
142
142
|
associations, others = other.left_outer_joins_values.partition do |join|
|
@@ -185,7 +185,7 @@ module ActiveRecord
|
|
185
185
|
|
186
186
|
def replace_from_clause?
|
187
187
|
relation.from_clause.empty? && !other.from_clause.empty? &&
|
188
|
-
relation.
|
188
|
+
relation.model.base_class == other.model.base_class
|
189
189
|
end
|
190
190
|
end
|
191
191
|
end
|
@@ -9,10 +9,11 @@ module ActiveRecord
|
|
9
9
|
end
|
10
10
|
|
11
11
|
if value.select_values.empty?
|
12
|
-
|
13
|
-
|
12
|
+
model = value.model
|
13
|
+
if model.composite_primary_key?
|
14
|
+
raise ArgumentError, "Cannot map composite primary key #{model.primary_key} to #{attribute.name}"
|
14
15
|
else
|
15
|
-
value = value.select(value.table[
|
16
|
+
value = value.select(value.table[model.primary_key])
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -77,6 +77,11 @@ module ActiveRecord
|
|
77
77
|
return ["1=0"] if attributes.empty?
|
78
78
|
|
79
79
|
attributes.flat_map do |key, value|
|
80
|
+
if key.is_a?(Array) && key.size == 1
|
81
|
+
key = key.first
|
82
|
+
value = value.flatten
|
83
|
+
end
|
84
|
+
|
80
85
|
if key.is_a?(Array)
|
81
86
|
queries = Array(value).map do |ids_set|
|
82
87
|
raise ArgumentError, "Expected corresponding value for #{key} to be an Array" unless ids_set.is_a?(Array)
|
@@ -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
|
#
|
@@ -696,26 +703,39 @@ module ActiveRecord
|
|
696
703
|
# # WHEN "conversations"."status" = 0 THEN 3
|
697
704
|
# # END ASC
|
698
705
|
#
|
699
|
-
|
700
|
-
|
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)
|
701
717
|
return spawn.none! if values.empty?
|
702
718
|
|
703
719
|
references = column_references([column])
|
704
720
|
self.references_values |= references unless references.empty?
|
705
721
|
|
706
|
-
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) }
|
707
723
|
arel_column = column.is_a?(Arel::Nodes::SqlLiteral) ? column : order_column(column.to_s)
|
708
724
|
|
709
|
-
|
710
|
-
if values.include?(nil)
|
711
|
-
arel_column.in(values.compact).or(arel_column.eq(nil))
|
712
|
-
else
|
713
|
-
arel_column.in(values)
|
714
|
-
end
|
725
|
+
scope = spawn.order!(build_case_for_value_position(arel_column, values, filter: filter))
|
715
726
|
|
716
|
-
|
717
|
-
|
718
|
-
|
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
|
719
739
|
end
|
720
740
|
|
721
741
|
# Replaces any existing order defined on the relation with the specified order.
|
@@ -1554,8 +1574,8 @@ module ActiveRecord
|
|
1554
1574
|
records.flatten!(1)
|
1555
1575
|
records.compact!
|
1556
1576
|
|
1557
|
-
unless records.all?(
|
1558
|
-
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__}."
|
1559
1579
|
end
|
1560
1580
|
|
1561
1581
|
spawn.excluding!(records + relations.flat_map(&:ids))
|
@@ -1575,7 +1595,7 @@ module ActiveRecord
|
|
1575
1595
|
|
1576
1596
|
def construct_join_dependency(associations, join_type) # :nodoc:
|
1577
1597
|
ActiveRecord::Associations::JoinDependency.new(
|
1578
|
-
|
1598
|
+
model, table, associations, join_type
|
1579
1599
|
)
|
1580
1600
|
end
|
1581
1601
|
|
@@ -1604,15 +1624,15 @@ module ActiveRecord
|
|
1604
1624
|
elsif opts.include?("?")
|
1605
1625
|
parts = [build_bound_sql_literal(opts, rest)]
|
1606
1626
|
else
|
1607
|
-
parts = [
|
1627
|
+
parts = [model.sanitize_sql(rest.empty? ? opts : [opts, *rest])]
|
1608
1628
|
end
|
1609
1629
|
when Hash
|
1610
1630
|
opts = opts.transform_keys do |key|
|
1611
1631
|
if key.is_a?(Array)
|
1612
|
-
key.map { |k|
|
1632
|
+
key.map { |k| model.attribute_aliases[k.to_s] || k.to_s }
|
1613
1633
|
else
|
1614
1634
|
key = key.to_s
|
1615
|
-
|
1635
|
+
model.attribute_aliases[key] || key
|
1616
1636
|
end
|
1617
1637
|
end
|
1618
1638
|
references = PredicateBuilder.references(opts)
|
@@ -1636,26 +1656,6 @@ module ActiveRecord
|
|
1636
1656
|
self
|
1637
1657
|
end
|
1638
1658
|
|
1639
|
-
protected
|
1640
|
-
def arel_columns(columns)
|
1641
|
-
columns.flat_map do |field|
|
1642
|
-
case field
|
1643
|
-
when Symbol
|
1644
|
-
arel_column(field.to_s) do |attr_name|
|
1645
|
-
adapter_class.quote_table_name(attr_name)
|
1646
|
-
end
|
1647
|
-
when String
|
1648
|
-
arel_column(field, &:itself)
|
1649
|
-
when Proc
|
1650
|
-
field.call
|
1651
|
-
when Hash
|
1652
|
-
arel_columns_from_hash(field)
|
1653
|
-
else
|
1654
|
-
field
|
1655
|
-
end
|
1656
|
-
end
|
1657
|
-
end
|
1658
|
-
|
1659
1659
|
private
|
1660
1660
|
def async
|
1661
1661
|
spawn.async!
|
@@ -1828,7 +1828,7 @@ module ActiveRecord
|
|
1828
1828
|
|
1829
1829
|
joins = joins_values.dup
|
1830
1830
|
if joins.last.is_a?(ActiveRecord::Associations::JoinDependency)
|
1831
|
-
stashed_eager_load = joins.pop if joins.last.base_klass ==
|
1831
|
+
stashed_eager_load = joins.pop if joins.last.base_klass == model
|
1832
1832
|
end
|
1833
1833
|
|
1834
1834
|
joins.each_with_index do |join, i|
|
@@ -1885,8 +1885,8 @@ module ActiveRecord
|
|
1885
1885
|
def build_select(arel)
|
1886
1886
|
if select_values.any?
|
1887
1887
|
arel.project(*arel_columns(select_values))
|
1888
|
-
elsif
|
1889
|
-
arel.project(*
|
1888
|
+
elsif model.ignored_columns.any? || model.enumerate_columns_in_select_statements
|
1889
|
+
arel.project(*model.column_names.map { |field| table[field] })
|
1890
1890
|
else
|
1891
1891
|
arel.project(table[Arel.star])
|
1892
1892
|
end
|
@@ -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
|
|
@@ -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,7 +2208,7 @@ 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
|
@@ -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.
|