activerecord 6.0.0.rc1 → 6.0.3.rc1
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 +251 -3
- data/README.rdoc +1 -1
- data/lib/active_record.rb +1 -0
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +0 -1
- data/lib/active_record/association_relation.rb +10 -8
- data/lib/active_record/associations.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +0 -1
- data/lib/active_record/associations/association.rb +5 -1
- data/lib/active_record/associations/builder/collection_association.rb +2 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -3
- data/lib/active_record/associations/collection_association.rb +6 -2
- data/lib/active_record/associations/collection_proxy.rb +2 -3
- data/lib/active_record/associations/has_many_association.rb +0 -1
- data/lib/active_record/associations/join_dependency.rb +23 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +12 -3
- data/lib/active_record/associations/preloader.rb +2 -3
- data/lib/active_record/associations/preloader/association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +0 -1
- data/lib/active_record/attribute_decorators.rb +0 -2
- data/lib/active_record/attribute_methods.rb +0 -51
- data/lib/active_record/attribute_methods/before_type_cast.rb +0 -1
- data/lib/active_record/attribute_methods/dirty.rb +8 -3
- data/lib/active_record/attribute_methods/primary_key.rb +0 -2
- data/lib/active_record/attribute_methods/read.rb +0 -1
- data/lib/active_record/attribute_methods/serialization.rb +0 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -2
- data/lib/active_record/attribute_methods/write.rb +0 -1
- data/lib/active_record/attributes.rb +0 -1
- data/lib/active_record/autosave_association.rb +11 -7
- data/lib/active_record/callbacks.rb +1 -2
- data/lib/active_record/coders/yaml_column.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +107 -13
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +21 -15
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +27 -27
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +55 -37
- data/lib/active_record/connection_adapters/abstract/transaction.rb +14 -7
- data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -25
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +25 -32
- data/lib/active_record/connection_adapters/connection_specification.rb +3 -4
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -12
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +3 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -8
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -4
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +9 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +39 -2
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -29
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +17 -3
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +8 -7
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +23 -8
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_handling.rb +17 -22
- data/lib/active_record/core.rb +8 -6
- data/lib/active_record/counter_cache.rb +4 -1
- data/lib/active_record/database_configurations.rb +60 -31
- data/lib/active_record/database_configurations/url_config.rb +0 -1
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +9 -0
- data/lib/active_record/explain.rb +0 -1
- data/lib/active_record/fixture_set/table_row.rb +0 -1
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +11 -9
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +0 -3
- data/lib/active_record/insert_all.rb +5 -6
- data/lib/active_record/internal_metadata.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +0 -1
- data/lib/active_record/log_subscriber.rb +1 -1
- data/lib/active_record/middleware/database_selector.rb +3 -4
- data/lib/active_record/middleware/database_selector/resolver.rb +5 -8
- data/lib/active_record/migration.rb +43 -32
- data/lib/active_record/migration/command_recorder.rb +6 -18
- data/lib/active_record/migration/compatibility.rb +3 -3
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/model_schema.rb +3 -2
- data/lib/active_record/nested_attributes.rb +0 -2
- data/lib/active_record/no_touching.rb +2 -2
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +4 -5
- data/lib/active_record/querying.rb +1 -1
- data/lib/active_record/railtie.rb +1 -2
- data/lib/active_record/railties/collection_cache_association_loading.rb +1 -1
- data/lib/active_record/railties/databases.rake +63 -23
- data/lib/active_record/reflection.rb +9 -9
- data/lib/active_record/relation.rb +13 -1
- data/lib/active_record/relation/batches.rb +0 -1
- data/lib/active_record/relation/calculations.rb +3 -5
- data/lib/active_record/relation/delegation.rb +7 -6
- data/lib/active_record/relation/finder_methods.rb +14 -4
- data/lib/active_record/relation/from_clause.rb +4 -0
- data/lib/active_record/relation/merger.rb +6 -3
- data/lib/active_record/relation/predicate_builder.rb +1 -5
- data/lib/active_record/relation/query_methods.rb +94 -55
- data/lib/active_record/relation/spawn_methods.rb +0 -1
- data/lib/active_record/relation/where_clause.rb +0 -1
- data/lib/active_record/result.rb +0 -1
- data/lib/active_record/sanitization.rb +30 -2
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +5 -1
- data/lib/active_record/schema_migration.rb +1 -1
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/scoping/default.rb +0 -1
- data/lib/active_record/scoping/named.rb +3 -3
- data/lib/active_record/store.rb +1 -1
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +21 -10
- data/lib/active_record/tasks/database_tasks.rb +76 -8
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -2
- data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +0 -1
- data/lib/active_record/test_databases.rb +1 -16
- data/lib/active_record/test_fixtures.rb +2 -1
- data/lib/active_record/timestamp.rb +26 -17
- data/lib/active_record/touch_later.rb +3 -2
- data/lib/active_record/transactions.rb +18 -19
- data/lib/active_record/type.rb +0 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +0 -1
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type_caster/connection.rb +16 -10
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/arel.rb +17 -6
- data/lib/arel/predications.rb +5 -6
- data/lib/arel/visitors/depth_first.rb +1 -2
- data/lib/arel/visitors/dot.rb +0 -1
- data/lib/arel/visitors/mssql.rb +0 -1
- data/lib/arel/visitors/oracle.rb +1 -2
- data/lib/arel/visitors/oracle12.rb +0 -1
- data/lib/arel/visitors/postgresql.rb +0 -1
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +23 -27
- data/lib/arel/visitors/visitor.rb +9 -6
- data/lib/arel/visitors/where_sql.rb +0 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration.rb +0 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +0 -1
- metadata +13 -9
@@ -89,7 +89,6 @@ module ActiveRecord
|
|
89
89
|
end
|
90
90
|
|
91
91
|
private
|
92
|
-
|
93
92
|
def merge_preloads
|
94
93
|
return if other.preload_values.empty? && other.includes_values.empty?
|
95
94
|
|
@@ -123,7 +122,9 @@ module ActiveRecord
|
|
123
122
|
end
|
124
123
|
end
|
125
124
|
|
126
|
-
join_dependency = other.construct_join_dependency(
|
125
|
+
join_dependency = other.construct_join_dependency(
|
126
|
+
associations, Arel::Nodes::InnerJoin
|
127
|
+
)
|
127
128
|
relation.joins!(join_dependency, *others)
|
128
129
|
end
|
129
130
|
end
|
@@ -135,7 +136,9 @@ module ActiveRecord
|
|
135
136
|
relation.left_outer_joins!(*other.left_outer_joins_values)
|
136
137
|
else
|
137
138
|
associations = other.left_outer_joins_values
|
138
|
-
join_dependency = other.construct_join_dependency(
|
139
|
+
join_dependency = other.construct_join_dependency(
|
140
|
+
associations, Arel::Nodes::OuterJoin
|
141
|
+
)
|
139
142
|
relation.joins!(join_dependency)
|
140
143
|
end
|
141
144
|
end
|
@@ -67,7 +67,7 @@ module ActiveRecord
|
|
67
67
|
|
68
68
|
attributes.flat_map do |key, value|
|
69
69
|
if value.is_a?(Hash) && !table.has_column?(key)
|
70
|
-
associated_predicate_builder(key).expand_from_hash(value)
|
70
|
+
table.associated_predicate_builder(key).expand_from_hash(value)
|
71
71
|
elsif table.associated_with?(key)
|
72
72
|
# Find the foreign key when using queries such as:
|
73
73
|
# Post.where(author: author)
|
@@ -114,10 +114,6 @@ module ActiveRecord
|
|
114
114
|
private
|
115
115
|
attr_reader :table
|
116
116
|
|
117
|
-
def associated_predicate_builder(association_name)
|
118
|
-
self.class.new(table.associated_table(association_name))
|
119
|
-
end
|
120
|
-
|
121
117
|
def convert_dot_notation_to_hash(attributes)
|
122
118
|
dot_notation = attributes.select do |k, v|
|
123
119
|
k.include?(".") && !v.is_a?(Hash)
|
@@ -51,8 +51,16 @@ module ActiveRecord
|
|
51
51
|
if not_behaves_as_nor?(opts)
|
52
52
|
ActiveSupport::Deprecation.warn(<<~MSG.squish)
|
53
53
|
NOT conditions will no longer behave as NOR in Rails 6.1.
|
54
|
-
To continue using NOR conditions, NOT each
|
55
|
-
(`#{
|
54
|
+
To continue using NOR conditions, NOT each condition individually
|
55
|
+
(`#{
|
56
|
+
opts.flat_map { |key, value|
|
57
|
+
if value.is_a?(Hash) && value.size > 1
|
58
|
+
value.map { |k, v| ".where.not(#{key.inspect} => { #{k.inspect} => ... })" }
|
59
|
+
else
|
60
|
+
".where.not(#{key.inspect} => ...)"
|
61
|
+
end
|
62
|
+
}.join
|
63
|
+
}`).
|
56
64
|
MSG
|
57
65
|
@scope.where_clause += where_clause.invert(:nor)
|
58
66
|
else
|
@@ -64,7 +72,10 @@ module ActiveRecord
|
|
64
72
|
|
65
73
|
private
|
66
74
|
def not_behaves_as_nor?(opts)
|
67
|
-
opts.is_a?(Hash)
|
75
|
+
return false unless opts.is_a?(Hash)
|
76
|
+
|
77
|
+
opts.any? { |k, v| v.is_a?(Hash) && v.size > 1 } ||
|
78
|
+
opts.size > 1
|
68
79
|
end
|
69
80
|
end
|
70
81
|
|
@@ -157,7 +168,7 @@ module ActiveRecord
|
|
157
168
|
end
|
158
169
|
|
159
170
|
def eager_load!(*args) # :nodoc:
|
160
|
-
self.eager_load_values
|
171
|
+
self.eager_load_values |= args
|
161
172
|
self
|
162
173
|
end
|
163
174
|
|
@@ -171,7 +182,7 @@ module ActiveRecord
|
|
171
182
|
end
|
172
183
|
|
173
184
|
def preload!(*args) # :nodoc:
|
174
|
-
self.preload_values
|
185
|
+
self.preload_values |= args
|
175
186
|
self
|
176
187
|
end
|
177
188
|
|
@@ -320,7 +331,7 @@ module ActiveRecord
|
|
320
331
|
def group!(*args) # :nodoc:
|
321
332
|
args.flatten!
|
322
333
|
|
323
|
-
self.group_values
|
334
|
+
self.group_values |= args
|
324
335
|
self
|
325
336
|
end
|
326
337
|
|
@@ -372,7 +383,7 @@ module ActiveRecord
|
|
372
383
|
|
373
384
|
# Same as #reorder but operates on relation in-place instead of copying.
|
374
385
|
def reorder!(*args) # :nodoc:
|
375
|
-
preprocess_order_args(args)
|
386
|
+
preprocess_order_args(args) unless args.all?(&:blank?)
|
376
387
|
|
377
388
|
self.reordering_value = true
|
378
389
|
self.order_values = args
|
@@ -488,7 +499,7 @@ module ActiveRecord
|
|
488
499
|
def joins!(*args) # :nodoc:
|
489
500
|
args.compact!
|
490
501
|
args.flatten!
|
491
|
-
self.joins_values
|
502
|
+
self.joins_values |= args
|
492
503
|
self
|
493
504
|
end
|
494
505
|
|
@@ -506,7 +517,7 @@ module ActiveRecord
|
|
506
517
|
def left_outer_joins!(*args) # :nodoc:
|
507
518
|
args.compact!
|
508
519
|
args.flatten!
|
509
|
-
self.left_outer_joins_values
|
520
|
+
self.left_outer_joins_values |= args
|
510
521
|
self
|
511
522
|
end
|
512
523
|
|
@@ -952,7 +963,7 @@ module ActiveRecord
|
|
952
963
|
def optimizer_hints!(*args) # :nodoc:
|
953
964
|
args.flatten!
|
954
965
|
|
955
|
-
self.optimizer_hints_values
|
966
|
+
self.optimizer_hints_values |= args
|
956
967
|
self
|
957
968
|
end
|
958
969
|
|
@@ -1005,9 +1016,9 @@ module ActiveRecord
|
|
1005
1016
|
@arel ||= build_arel(aliases)
|
1006
1017
|
end
|
1007
1018
|
|
1008
|
-
def construct_join_dependency(associations) # :nodoc:
|
1019
|
+
def construct_join_dependency(associations, join_type) # :nodoc:
|
1009
1020
|
ActiveRecord::Associations::JoinDependency.new(
|
1010
|
-
klass, table, associations
|
1021
|
+
klass, table, associations, join_type
|
1011
1022
|
)
|
1012
1023
|
end
|
1013
1024
|
|
@@ -1083,38 +1094,68 @@ module ActiveRecord
|
|
1083
1094
|
end
|
1084
1095
|
end
|
1085
1096
|
|
1086
|
-
def
|
1097
|
+
def select_association_list(associations)
|
1098
|
+
result = []
|
1087
1099
|
associations.each do |association|
|
1088
1100
|
case association
|
1089
1101
|
when Hash, Symbol, Array
|
1090
|
-
|
1102
|
+
result << association
|
1091
1103
|
else
|
1092
|
-
|
1104
|
+
yield if block_given?
|
1093
1105
|
end
|
1094
1106
|
end
|
1107
|
+
result
|
1108
|
+
end
|
1109
|
+
|
1110
|
+
def valid_association_list(associations)
|
1111
|
+
select_association_list(associations) do
|
1112
|
+
raise ArgumentError, "only Hash, Symbol and Array are allowed"
|
1113
|
+
end
|
1095
1114
|
end
|
1096
1115
|
|
1097
1116
|
def build_left_outer_joins(manager, outer_joins, aliases)
|
1098
|
-
buckets = {
|
1117
|
+
buckets = Hash.new { |h, k| h[k] = [] }
|
1118
|
+
buckets[:association_join] = valid_association_list(outer_joins)
|
1099
1119
|
build_join_query(manager, buckets, Arel::Nodes::OuterJoin, aliases)
|
1100
1120
|
end
|
1101
1121
|
|
1102
1122
|
def build_joins(manager, joins, aliases)
|
1123
|
+
buckets = Hash.new { |h, k| h[k] = [] }
|
1124
|
+
|
1103
1125
|
unless left_outer_joins_values.empty?
|
1104
1126
|
left_joins = valid_association_list(left_outer_joins_values.flatten)
|
1105
|
-
|
1127
|
+
buckets[:stashed_join] << construct_join_dependency(left_joins, Arel::Nodes::OuterJoin)
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
if joins.last.is_a?(ActiveRecord::Associations::JoinDependency)
|
1131
|
+
buckets[:stashed_join] << joins.pop if joins.last.base_klass == klass
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
joins.map! do |join|
|
1135
|
+
if join.is_a?(String)
|
1136
|
+
table.create_string_join(Arel.sql(join.strip)) unless join.blank?
|
1137
|
+
else
|
1138
|
+
join
|
1139
|
+
end
|
1140
|
+
end.delete_if(&:blank?).uniq!
|
1141
|
+
|
1142
|
+
while joins.first.is_a?(Arel::Nodes::Join)
|
1143
|
+
join_node = joins.shift
|
1144
|
+
if join_node.is_a?(Arel::Nodes::StringJoin) && !buckets[:stashed_join].empty?
|
1145
|
+
buckets[:join_node] << join_node
|
1146
|
+
else
|
1147
|
+
buckets[:leading_join] << join_node
|
1148
|
+
end
|
1106
1149
|
end
|
1107
1150
|
|
1108
|
-
|
1151
|
+
joins.each do |join|
|
1109
1152
|
case join
|
1110
|
-
when String
|
1111
|
-
:string_join
|
1112
1153
|
when Hash, Symbol, Array
|
1113
|
-
:association_join
|
1154
|
+
buckets[:association_join] << join
|
1114
1155
|
when ActiveRecord::Associations::JoinDependency
|
1115
|
-
:stashed_join
|
1156
|
+
buckets[:stashed_join] << join
|
1116
1157
|
when Arel::Nodes::Join
|
1117
|
-
:join_node
|
1158
|
+
buckets[:join_node] << join
|
1118
1159
|
else
|
1119
1160
|
raise "unknown class: %s" % join.class.name
|
1120
1161
|
end
|
@@ -1124,31 +1165,21 @@ module ActiveRecord
|
|
1124
1165
|
end
|
1125
1166
|
|
1126
1167
|
def build_join_query(manager, buckets, join_type, aliases)
|
1127
|
-
buckets.default = []
|
1128
|
-
|
1129
1168
|
association_joins = buckets[:association_join]
|
1130
1169
|
stashed_joins = buckets[:stashed_join]
|
1131
|
-
|
1132
|
-
|
1170
|
+
leading_joins = buckets[:leading_join]
|
1171
|
+
join_nodes = buckets[:join_node]
|
1133
1172
|
|
1134
|
-
|
1135
|
-
|
1173
|
+
join_sources = manager.join_sources
|
1174
|
+
join_sources.concat(leading_joins) unless leading_joins.empty?
|
1136
1175
|
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
manager.join_sources.concat(join_list)
|
1143
|
-
|
1144
|
-
alias_tracker.aliases
|
1145
|
-
end
|
1176
|
+
unless association_joins.empty? && stashed_joins.empty?
|
1177
|
+
alias_tracker = alias_tracker(leading_joins + join_nodes, aliases)
|
1178
|
+
join_dependency = construct_join_dependency(association_joins, join_type)
|
1179
|
+
join_sources.concat(join_dependency.join_constraints(stashed_joins, alias_tracker))
|
1180
|
+
end
|
1146
1181
|
|
1147
|
-
|
1148
|
-
joins
|
1149
|
-
.flatten
|
1150
|
-
.reject(&:blank?)
|
1151
|
-
.map { |join| table.create_string_join(Arel.sql(join)) }
|
1182
|
+
join_sources.concat(join_nodes) unless join_nodes.empty?
|
1152
1183
|
end
|
1153
1184
|
|
1154
1185
|
def build_select(arel)
|
@@ -1165,8 +1196,9 @@ module ActiveRecord
|
|
1165
1196
|
columns.flat_map do |field|
|
1166
1197
|
case field
|
1167
1198
|
when Symbol
|
1168
|
-
field
|
1169
|
-
|
1199
|
+
arel_column(field.to_s) do |attr_name|
|
1200
|
+
connection.quote_table_name(attr_name)
|
1201
|
+
end
|
1170
1202
|
when String
|
1171
1203
|
arel_column(field, &:itself)
|
1172
1204
|
when Proc
|
@@ -1189,7 +1221,9 @@ module ActiveRecord
|
|
1189
1221
|
end
|
1190
1222
|
|
1191
1223
|
def table_name_matches?(from)
|
1192
|
-
|
1224
|
+
table_name = Regexp.escape(table.name)
|
1225
|
+
quoted_table_name = Regexp.escape(connection.quote_table_name(table.name))
|
1226
|
+
/(?:\A|(?<!FROM)\s)(?:\b#{table_name}\b|#{quoted_table_name})(?!\.)/i.match?(from.to_s)
|
1193
1227
|
end
|
1194
1228
|
|
1195
1229
|
def reverse_sql_order(order_query)
|
@@ -1253,6 +1287,7 @@ module ActiveRecord
|
|
1253
1287
|
end
|
1254
1288
|
|
1255
1289
|
def preprocess_order_args(order_args)
|
1290
|
+
order_args.reject!(&:blank?)
|
1256
1291
|
order_args.map! do |arg|
|
1257
1292
|
klass.sanitize_sql_for_order(arg)
|
1258
1293
|
end
|
@@ -1260,7 +1295,7 @@ module ActiveRecord
|
|
1260
1295
|
|
1261
1296
|
@klass.disallow_raw_sql!(
|
1262
1297
|
order_args.flat_map { |a| a.is_a?(Hash) ? a.keys : a },
|
1263
|
-
permit:
|
1298
|
+
permit: connection.column_name_with_order_matcher
|
1264
1299
|
)
|
1265
1300
|
|
1266
1301
|
validate_order_args(order_args)
|
@@ -1273,20 +1308,14 @@ module ActiveRecord
|
|
1273
1308
|
order_args.map! do |arg|
|
1274
1309
|
case arg
|
1275
1310
|
when Symbol
|
1276
|
-
arg
|
1277
|
-
arel_column(arg) {
|
1278
|
-
Arel.sql(connection.quote_table_name(arg))
|
1279
|
-
}.asc
|
1311
|
+
order_column(arg.to_s).asc
|
1280
1312
|
when Hash
|
1281
1313
|
arg.map { |field, dir|
|
1282
1314
|
case field
|
1283
1315
|
when Arel::Nodes::SqlLiteral
|
1284
1316
|
field.send(dir.downcase)
|
1285
1317
|
else
|
1286
|
-
field
|
1287
|
-
arel_column(field) {
|
1288
|
-
Arel.sql(connection.quote_table_name(field))
|
1289
|
-
}.send(dir.downcase)
|
1318
|
+
order_column(field.to_s).send(dir.downcase)
|
1290
1319
|
end
|
1291
1320
|
}
|
1292
1321
|
else
|
@@ -1295,6 +1324,16 @@ module ActiveRecord
|
|
1295
1324
|
end.flatten!
|
1296
1325
|
end
|
1297
1326
|
|
1327
|
+
def order_column(field)
|
1328
|
+
arel_column(field) do |attr_name|
|
1329
|
+
if attr_name == "count" && !group_values.empty?
|
1330
|
+
arel_attribute(attr_name)
|
1331
|
+
else
|
1332
|
+
Arel.sql(connection.quote_table_name(attr_name))
|
1333
|
+
end
|
1334
|
+
end
|
1335
|
+
end
|
1336
|
+
|
1298
1337
|
# Checks to make sure that the arguments are not blank. Note that if some
|
1299
1338
|
# blank-like object were initially passed into the query method, then this
|
1300
1339
|
# method will not raise an error.
|
data/lib/active_record/result.rb
CHANGED
@@ -61,8 +61,9 @@ module ActiveRecord
|
|
61
61
|
# # => "id ASC"
|
62
62
|
def sanitize_sql_for_order(condition)
|
63
63
|
if condition.is_a?(Array) && condition.first.to_s.include?("?")
|
64
|
-
disallow_raw_sql!(
|
65
|
-
|
64
|
+
disallow_raw_sql!(
|
65
|
+
[condition.first],
|
66
|
+
permit: connection.column_name_with_order_matcher
|
66
67
|
)
|
67
68
|
|
68
69
|
# Ensure we aren't dealing with a subclass of String that might
|
@@ -133,6 +134,33 @@ module ActiveRecord
|
|
133
134
|
end
|
134
135
|
end
|
135
136
|
|
137
|
+
def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc:
|
138
|
+
unexpected = nil
|
139
|
+
args.each do |arg|
|
140
|
+
next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s)
|
141
|
+
(unexpected ||= []) << arg
|
142
|
+
end
|
143
|
+
|
144
|
+
return unless unexpected
|
145
|
+
|
146
|
+
if allow_unsafe_raw_sql == :deprecated
|
147
|
+
ActiveSupport::Deprecation.warn(
|
148
|
+
"Dangerous query method (method whose arguments are used as raw " \
|
149
|
+
"SQL) called with non-attribute argument(s): " \
|
150
|
+
"#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
|
151
|
+
"arguments will be disallowed in Rails 6.1. This method should " \
|
152
|
+
"not be called with user-provided values, such as request " \
|
153
|
+
"parameters or model attributes. Known-safe values can be passed " \
|
154
|
+
"by wrapping them in Arel.sql()."
|
155
|
+
)
|
156
|
+
else
|
157
|
+
raise(ActiveRecord::UnknownAttributeReference,
|
158
|
+
"Query method called with non-attribute argument(s): " +
|
159
|
+
unexpected.map(&:inspect).join(", ")
|
160
|
+
)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
136
164
|
private
|
137
165
|
def replace_bind_variables(statement, values)
|
138
166
|
raise_if_bind_arity_mismatch(statement, statement.count("?"), values.size)
|
data/lib/active_record/schema.rb
CHANGED
@@ -146,7 +146,11 @@ HEADER
|
|
146
146
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
147
147
|
next if column.name == pk
|
148
148
|
type, colspec = column_spec(column)
|
149
|
-
|
149
|
+
if type.is_a?(Symbol)
|
150
|
+
tbl.print " t.#{type} #{column.name.inspect}"
|
151
|
+
else
|
152
|
+
tbl.print " t.column #{column.name.inspect}, #{type.inspect}"
|
153
|
+
end
|
150
154
|
tbl.print ", #{format_colspec(colspec)}" if colspec.present?
|
151
155
|
tbl.puts
|
152
156
|
end
|