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.

Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +251 -3
  3. data/README.rdoc +1 -1
  4. data/lib/active_record.rb +1 -0
  5. data/lib/active_record/advisory_lock_base.rb +18 -0
  6. data/lib/active_record/aggregations.rb +0 -1
  7. data/lib/active_record/association_relation.rb +10 -8
  8. data/lib/active_record/associations.rb +2 -2
  9. data/lib/active_record/associations/alias_tracker.rb +0 -1
  10. data/lib/active_record/associations/association.rb +5 -1
  11. data/lib/active_record/associations/builder/collection_association.rb +2 -2
  12. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -3
  13. data/lib/active_record/associations/collection_association.rb +6 -2
  14. data/lib/active_record/associations/collection_proxy.rb +2 -3
  15. data/lib/active_record/associations/has_many_association.rb +0 -1
  16. data/lib/active_record/associations/join_dependency.rb +23 -9
  17. data/lib/active_record/associations/join_dependency/join_association.rb +12 -3
  18. data/lib/active_record/associations/preloader.rb +2 -3
  19. data/lib/active_record/associations/preloader/association.rb +3 -1
  20. data/lib/active_record/attribute_assignment.rb +0 -1
  21. data/lib/active_record/attribute_decorators.rb +0 -2
  22. data/lib/active_record/attribute_methods.rb +0 -51
  23. data/lib/active_record/attribute_methods/before_type_cast.rb +0 -1
  24. data/lib/active_record/attribute_methods/dirty.rb +8 -3
  25. data/lib/active_record/attribute_methods/primary_key.rb +0 -2
  26. data/lib/active_record/attribute_methods/read.rb +0 -1
  27. data/lib/active_record/attribute_methods/serialization.rb +0 -1
  28. data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -2
  29. data/lib/active_record/attribute_methods/write.rb +0 -1
  30. data/lib/active_record/attributes.rb +0 -1
  31. data/lib/active_record/autosave_association.rb +11 -7
  32. data/lib/active_record/callbacks.rb +1 -2
  33. data/lib/active_record/coders/yaml_column.rb +0 -1
  34. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +107 -13
  35. data/lib/active_record/connection_adapters/abstract/database_statements.rb +21 -15
  36. data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -5
  37. data/lib/active_record/connection_adapters/abstract/quoting.rb +53 -0
  38. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -2
  39. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +27 -27
  40. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
  41. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +55 -37
  42. data/lib/active_record/connection_adapters/abstract/transaction.rb +14 -7
  43. data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -25
  44. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +25 -32
  45. data/lib/active_record/connection_adapters/connection_specification.rb +3 -4
  46. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -2
  47. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  48. data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -12
  49. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
  50. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  51. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +1 -2
  52. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +3 -1
  53. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -8
  54. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -4
  55. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +9 -3
  56. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  57. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  58. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  59. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +0 -1
  60. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  61. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  62. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +0 -1
  63. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +0 -1
  64. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  65. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +0 -1
  66. data/lib/active_record/connection_adapters/postgresql/quoting.rb +39 -2
  67. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  68. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -2
  69. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  70. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  71. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -29
  72. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  73. data/lib/active_record/connection_adapters/postgresql_adapter.rb +17 -3
  74. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +8 -7
  75. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -3
  76. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +3 -3
  77. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +23 -8
  78. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  79. data/lib/active_record/connection_handling.rb +17 -22
  80. data/lib/active_record/core.rb +8 -6
  81. data/lib/active_record/counter_cache.rb +4 -1
  82. data/lib/active_record/database_configurations.rb +60 -31
  83. data/lib/active_record/database_configurations/url_config.rb +0 -1
  84. data/lib/active_record/dynamic_matchers.rb +2 -3
  85. data/lib/active_record/enum.rb +9 -0
  86. data/lib/active_record/explain.rb +0 -1
  87. data/lib/active_record/fixture_set/table_row.rb +0 -1
  88. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  89. data/lib/active_record/fixtures.rb +11 -9
  90. data/lib/active_record/gem_version.rb +1 -1
  91. data/lib/active_record/inheritance.rb +0 -3
  92. data/lib/active_record/insert_all.rb +5 -6
  93. data/lib/active_record/internal_metadata.rb +1 -1
  94. data/lib/active_record/locking/optimistic.rb +0 -1
  95. data/lib/active_record/log_subscriber.rb +1 -1
  96. data/lib/active_record/middleware/database_selector.rb +3 -4
  97. data/lib/active_record/middleware/database_selector/resolver.rb +5 -8
  98. data/lib/active_record/migration.rb +43 -32
  99. data/lib/active_record/migration/command_recorder.rb +6 -18
  100. data/lib/active_record/migration/compatibility.rb +3 -3
  101. data/lib/active_record/migration/join_table.rb +0 -1
  102. data/lib/active_record/model_schema.rb +3 -2
  103. data/lib/active_record/nested_attributes.rb +0 -2
  104. data/lib/active_record/no_touching.rb +2 -2
  105. data/lib/active_record/null_relation.rb +0 -1
  106. data/lib/active_record/persistence.rb +4 -5
  107. data/lib/active_record/querying.rb +1 -1
  108. data/lib/active_record/railtie.rb +1 -2
  109. data/lib/active_record/railties/collection_cache_association_loading.rb +1 -1
  110. data/lib/active_record/railties/databases.rake +63 -23
  111. data/lib/active_record/reflection.rb +9 -9
  112. data/lib/active_record/relation.rb +13 -1
  113. data/lib/active_record/relation/batches.rb +0 -1
  114. data/lib/active_record/relation/calculations.rb +3 -5
  115. data/lib/active_record/relation/delegation.rb +7 -6
  116. data/lib/active_record/relation/finder_methods.rb +14 -4
  117. data/lib/active_record/relation/from_clause.rb +4 -0
  118. data/lib/active_record/relation/merger.rb +6 -3
  119. data/lib/active_record/relation/predicate_builder.rb +1 -5
  120. data/lib/active_record/relation/query_methods.rb +94 -55
  121. data/lib/active_record/relation/spawn_methods.rb +0 -1
  122. data/lib/active_record/relation/where_clause.rb +0 -1
  123. data/lib/active_record/result.rb +0 -1
  124. data/lib/active_record/sanitization.rb +30 -2
  125. data/lib/active_record/schema.rb +1 -1
  126. data/lib/active_record/schema_dumper.rb +5 -1
  127. data/lib/active_record/schema_migration.rb +1 -1
  128. data/lib/active_record/scoping.rb +0 -1
  129. data/lib/active_record/scoping/default.rb +0 -1
  130. data/lib/active_record/scoping/named.rb +3 -3
  131. data/lib/active_record/store.rb +1 -1
  132. data/lib/active_record/suppressor.rb +2 -2
  133. data/lib/active_record/table_metadata.rb +21 -10
  134. data/lib/active_record/tasks/database_tasks.rb +76 -8
  135. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -2
  136. data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -1
  137. data/lib/active_record/tasks/sqlite_database_tasks.rb +0 -1
  138. data/lib/active_record/test_databases.rb +1 -16
  139. data/lib/active_record/test_fixtures.rb +2 -1
  140. data/lib/active_record/timestamp.rb +26 -17
  141. data/lib/active_record/touch_later.rb +3 -2
  142. data/lib/active_record/transactions.rb +18 -19
  143. data/lib/active_record/type.rb +0 -1
  144. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  145. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  146. data/lib/active_record/type/serialized.rb +0 -1
  147. data/lib/active_record/type/type_map.rb +0 -1
  148. data/lib/active_record/type/unsigned_integer.rb +0 -1
  149. data/lib/active_record/type_caster/connection.rb +16 -10
  150. data/lib/active_record/validations.rb +3 -3
  151. data/lib/active_record/validations/associated.rb +1 -2
  152. data/lib/arel.rb +17 -6
  153. data/lib/arel/predications.rb +5 -6
  154. data/lib/arel/visitors/depth_first.rb +1 -2
  155. data/lib/arel/visitors/dot.rb +0 -1
  156. data/lib/arel/visitors/mssql.rb +0 -1
  157. data/lib/arel/visitors/oracle.rb +1 -2
  158. data/lib/arel/visitors/oracle12.rb +0 -1
  159. data/lib/arel/visitors/postgresql.rb +0 -1
  160. data/lib/arel/visitors/sqlite.rb +0 -1
  161. data/lib/arel/visitors/to_sql.rb +23 -27
  162. data/lib/arel/visitors/visitor.rb +9 -6
  163. data/lib/arel/visitors/where_sql.rb +0 -1
  164. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  165. data/lib/rails/generators/active_record/migration.rb +0 -1
  166. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +1 -1
  167. data/lib/rails/generators/active_record/model/model_generator.rb +0 -1
  168. 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(associations)
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(associations)
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 conditions manually
55
- (`#{ opts.keys.map { |key| ".where.not(#{key.inspect} => ...)" }.join }`).
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) && opts.size > 1
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 += args
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 += args
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 += args
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 += args
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 += args
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 += args
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 valid_association_list(associations)
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
- # valid
1102
+ result << association
1091
1103
  else
1092
- raise ArgumentError, "only Hash, Symbol and Array are allowed"
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 = { association_join: valid_association_list(outer_joins) }
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
- joins << construct_join_dependency(left_joins)
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
- buckets = joins.group_by do |join|
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
- join_nodes = buckets[:join_node].uniq
1132
- string_joins = buckets[:string_join].map(&:strip).uniq
1170
+ leading_joins = buckets[:leading_join]
1171
+ join_nodes = buckets[:join_node]
1133
1172
 
1134
- join_list = join_nodes + convert_join_strings_to_ast(string_joins)
1135
- alias_tracker = alias_tracker(join_list, aliases)
1173
+ join_sources = manager.join_sources
1174
+ join_sources.concat(leading_joins) unless leading_joins.empty?
1136
1175
 
1137
- join_dependency = construct_join_dependency(association_joins)
1138
-
1139
- joins = join_dependency.join_constraints(stashed_joins, join_type, alias_tracker)
1140
- joins.each { |join| manager.from(join) }
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
- def convert_join_strings_to_ast(joins)
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 = field.to_s
1169
- arel_column(field, &connection.method(:quote_table_name))
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
- /(?:\A|(?<!FROM)\s)(?:\b#{table.name}\b|#{connection.quote_table_name(table.name)})(?!\.)/i.match?(from.to_s)
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: AttributeMethods::ClassMethods::COLUMN_NAME_WITH_ORDER
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 = arg.to_s
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 = field.to_s
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.
@@ -67,7 +67,6 @@ module ActiveRecord
67
67
  end
68
68
 
69
69
  private
70
-
71
70
  def relation_with(values)
72
71
  result = Relation.create(klass, values: values)
73
72
  result.extend(*extending_values) if extending_values.any?
@@ -87,7 +87,6 @@ module ActiveRecord
87
87
  end
88
88
 
89
89
  protected
90
-
91
90
  attr_reader :predicates
92
91
 
93
92
  def referenced_columns
@@ -132,7 +132,6 @@ module ActiveRecord
132
132
  end
133
133
 
134
134
  private
135
-
136
135
  def column_type(name, type_overrides = {})
137
136
  type_overrides.fetch(name) do
138
137
  column_types.fetch(name, Type.default_value)
@@ -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!([condition.first],
65
- permit: AttributeMethods::ClassMethods::COLUMN_NAME_WITH_ORDER
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)
@@ -50,7 +50,7 @@ module ActiveRecord
50
50
  instance_eval(&block)
51
51
 
52
52
  if info[:version].present?
53
- ActiveRecord::SchemaMigration.create_table
53
+ connection.schema_migration.create_table
54
54
  connection.assume_migrated_upto_version(info[:version])
55
55
  end
56
56
 
@@ -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
- tbl.print " t.#{type} #{column.name.inspect}"
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
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  version_options = connection.internal_string_options_for_primary_key
32
32
 
33
33
  connection.create_table(table_name, id: false) do |t|
34
- t.string :version, version_options
34
+ t.string :version, **version_options
35
35
  end
36
36
  end
37
37
  end