activerecord 6.0.0 → 6.1.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (270) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1045 -575
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_record.rb +7 -13
  6. data/lib/active_record/aggregations.rb +5 -6
  7. data/lib/active_record/association_relation.rb +30 -10
  8. data/lib/active_record/associations.rb +120 -13
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +49 -29
  11. data/lib/active_record/associations/association_scope.rb +19 -15
  12. data/lib/active_record/associations/belongs_to_association.rb +22 -8
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
  14. data/lib/active_record/associations/builder/association.rb +32 -5
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  16. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
  18. data/lib/active_record/associations/builder/has_many.rb +6 -2
  19. data/lib/active_record/associations/builder/has_one.rb +11 -14
  20. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  21. data/lib/active_record/associations/collection_association.rb +25 -8
  22. data/lib/active_record/associations/collection_proxy.rb +14 -7
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +24 -3
  25. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  26. data/lib/active_record/associations/has_one_association.rb +15 -1
  27. data/lib/active_record/associations/join_dependency.rb +77 -42
  28. data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
  29. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  30. data/lib/active_record/associations/preloader.rb +13 -8
  31. data/lib/active_record/associations/preloader/association.rb +51 -25
  32. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  33. data/lib/active_record/associations/singular_association.rb +1 -1
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/attribute_assignment.rb +10 -9
  36. data/lib/active_record/attribute_methods.rb +64 -54
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
  38. data/lib/active_record/attribute_methods/dirty.rb +3 -13
  39. data/lib/active_record/attribute_methods/primary_key.rb +6 -4
  40. data/lib/active_record/attribute_methods/query.rb +3 -6
  41. data/lib/active_record/attribute_methods/read.rb +8 -12
  42. data/lib/active_record/attribute_methods/serialization.rb +11 -6
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +12 -21
  45. data/lib/active_record/attributes.rb +33 -9
  46. data/lib/active_record/autosave_association.rb +63 -44
  47. data/lib/active_record/base.rb +2 -14
  48. data/lib/active_record/callbacks.rb +153 -24
  49. data/lib/active_record/coders/yaml_column.rb +1 -2
  50. data/lib/active_record/connection_adapters.rb +50 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +202 -138
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +87 -38
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -10
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +141 -52
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +74 -77
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -115
  64. data/lib/active_record/connection_adapters/column.rb +15 -1
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  67. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
  77. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
  81. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
  95. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
  97. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  99. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
  100. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  101. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  102. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
  103. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  104. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  105. data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -65
  106. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  107. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  108. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
  109. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
  110. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  111. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
  112. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -57
  113. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  114. data/lib/active_record/connection_handling.rb +219 -81
  115. data/lib/active_record/core.rb +253 -67
  116. data/lib/active_record/counter_cache.rb +4 -1
  117. data/lib/active_record/database_configurations.rb +124 -85
  118. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  119. data/lib/active_record/database_configurations/database_config.rb +52 -9
  120. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  121. data/lib/active_record/database_configurations/url_config.rb +15 -41
  122. data/lib/active_record/delegated_type.rb +209 -0
  123. data/lib/active_record/destroy_association_async_job.rb +36 -0
  124. data/lib/active_record/dynamic_matchers.rb +2 -3
  125. data/lib/active_record/enum.rb +82 -38
  126. data/lib/active_record/errors.rb +47 -12
  127. data/lib/active_record/explain.rb +9 -5
  128. data/lib/active_record/explain_subscriber.rb +1 -1
  129. data/lib/active_record/fixture_set/file.rb +10 -17
  130. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  131. data/lib/active_record/fixture_set/render_context.rb +1 -1
  132. data/lib/active_record/fixture_set/table_row.rb +2 -3
  133. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  134. data/lib/active_record/fixtures.rb +58 -12
  135. data/lib/active_record/gem_version.rb +2 -2
  136. data/lib/active_record/inheritance.rb +40 -21
  137. data/lib/active_record/insert_all.rb +39 -10
  138. data/lib/active_record/integration.rb +3 -5
  139. data/lib/active_record/internal_metadata.rb +16 -7
  140. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  141. data/lib/active_record/locking/optimistic.rb +33 -18
  142. data/lib/active_record/locking/pessimistic.rb +6 -2
  143. data/lib/active_record/log_subscriber.rb +28 -9
  144. data/lib/active_record/middleware/database_selector.rb +4 -2
  145. data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
  146. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  147. data/lib/active_record/migration.rb +115 -85
  148. data/lib/active_record/migration/command_recorder.rb +53 -45
  149. data/lib/active_record/migration/compatibility.rb +71 -20
  150. data/lib/active_record/migration/join_table.rb +0 -1
  151. data/lib/active_record/model_schema.rb +120 -15
  152. data/lib/active_record/nested_attributes.rb +2 -5
  153. data/lib/active_record/no_touching.rb +1 -1
  154. data/lib/active_record/null_relation.rb +0 -1
  155. data/lib/active_record/persistence.rb +50 -46
  156. data/lib/active_record/query_cache.rb +15 -5
  157. data/lib/active_record/querying.rb +12 -7
  158. data/lib/active_record/railtie.rb +65 -45
  159. data/lib/active_record/railties/console_sandbox.rb +2 -4
  160. data/lib/active_record/railties/databases.rake +277 -97
  161. data/lib/active_record/readonly_attributes.rb +4 -0
  162. data/lib/active_record/reflection.rb +77 -63
  163. data/lib/active_record/relation.rb +107 -67
  164. data/lib/active_record/relation/batches.rb +38 -32
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  166. data/lib/active_record/relation/calculations.rb +102 -45
  167. data/lib/active_record/relation/delegation.rb +9 -7
  168. data/lib/active_record/relation/finder_methods.rb +55 -17
  169. data/lib/active_record/relation/from_clause.rb +5 -1
  170. data/lib/active_record/relation/merger.rb +27 -26
  171. data/lib/active_record/relation/predicate_builder.rb +59 -40
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  174. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  175. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  176. data/lib/active_record/relation/query_methods.rb +343 -180
  177. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  178. data/lib/active_record/relation/spawn_methods.rb +8 -8
  179. data/lib/active_record/relation/where_clause.rb +107 -61
  180. data/lib/active_record/result.rb +41 -34
  181. data/lib/active_record/runtime_registry.rb +2 -2
  182. data/lib/active_record/sanitization.rb +6 -17
  183. data/lib/active_record/schema_dumper.rb +34 -4
  184. data/lib/active_record/schema_migration.rb +2 -8
  185. data/lib/active_record/scoping.rb +0 -1
  186. data/lib/active_record/scoping/default.rb +0 -1
  187. data/lib/active_record/scoping/named.rb +7 -18
  188. data/lib/active_record/secure_token.rb +16 -8
  189. data/lib/active_record/serialization.rb +5 -3
  190. data/lib/active_record/signed_id.rb +116 -0
  191. data/lib/active_record/statement_cache.rb +20 -4
  192. data/lib/active_record/store.rb +3 -3
  193. data/lib/active_record/suppressor.rb +2 -2
  194. data/lib/active_record/table_metadata.rb +42 -36
  195. data/lib/active_record/tasks/database_tasks.rb +140 -113
  196. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
  197. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
  198. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
  199. data/lib/active_record/test_databases.rb +5 -4
  200. data/lib/active_record/test_fixtures.rb +38 -16
  201. data/lib/active_record/timestamp.rb +4 -7
  202. data/lib/active_record/touch_later.rb +20 -21
  203. data/lib/active_record/transactions.rb +26 -73
  204. data/lib/active_record/type.rb +8 -2
  205. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  206. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  207. data/lib/active_record/type/serialized.rb +6 -3
  208. data/lib/active_record/type/time.rb +10 -0
  209. data/lib/active_record/type/type_map.rb +0 -1
  210. data/lib/active_record/type/unsigned_integer.rb +0 -1
  211. data/lib/active_record/type_caster/connection.rb +0 -1
  212. data/lib/active_record/type_caster/map.rb +8 -5
  213. data/lib/active_record/validations.rb +3 -3
  214. data/lib/active_record/validations/associated.rb +1 -2
  215. data/lib/active_record/validations/numericality.rb +35 -0
  216. data/lib/active_record/validations/uniqueness.rb +24 -4
  217. data/lib/arel.rb +15 -12
  218. data/lib/arel/attributes/attribute.rb +4 -0
  219. data/lib/arel/collectors/bind.rb +5 -0
  220. data/lib/arel/collectors/composite.rb +8 -0
  221. data/lib/arel/collectors/sql_string.rb +7 -0
  222. data/lib/arel/collectors/substitute_binds.rb +7 -0
  223. data/lib/arel/nodes.rb +3 -1
  224. data/lib/arel/nodes/binary.rb +82 -8
  225. data/lib/arel/nodes/bind_param.rb +8 -0
  226. data/lib/arel/nodes/casted.rb +21 -9
  227. data/lib/arel/nodes/equality.rb +6 -9
  228. data/lib/arel/nodes/grouping.rb +3 -0
  229. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  230. data/lib/arel/nodes/in.rb +8 -1
  231. data/lib/arel/nodes/infix_operation.rb +13 -1
  232. data/lib/arel/nodes/join_source.rb +1 -1
  233. data/lib/arel/nodes/node.rb +7 -6
  234. data/lib/arel/nodes/ordering.rb +27 -0
  235. data/lib/arel/nodes/sql_literal.rb +3 -0
  236. data/lib/arel/nodes/table_alias.rb +7 -3
  237. data/lib/arel/nodes/unary.rb +0 -1
  238. data/lib/arel/predications.rb +17 -24
  239. data/lib/arel/select_manager.rb +1 -2
  240. data/lib/arel/table.rb +13 -5
  241. data/lib/arel/visitors.rb +0 -7
  242. data/lib/arel/visitors/dot.rb +14 -3
  243. data/lib/arel/visitors/mysql.rb +11 -1
  244. data/lib/arel/visitors/postgresql.rb +15 -5
  245. data/lib/arel/visitors/sqlite.rb +0 -1
  246. data/lib/arel/visitors/to_sql.rb +89 -79
  247. data/lib/arel/visitors/visitor.rb +0 -1
  248. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  249. data/lib/rails/generators/active_record/migration.rb +6 -2
  250. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  251. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  252. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  253. data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
  254. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  255. metadata +30 -27
  256. data/lib/active_record/attribute_decorators.rb +0 -90
  257. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  258. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  259. data/lib/active_record/define_callbacks.rb +0 -22
  260. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  261. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  262. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  263. data/lib/arel/attributes.rb +0 -22
  264. data/lib/arel/visitors/depth_first.rb +0 -204
  265. data/lib/arel/visitors/ibm_db.rb +0 -34
  266. data/lib/arel/visitors/informix.rb +0 -62
  267. data/lib/arel/visitors/mssql.rb +0 -157
  268. data/lib/arel/visitors/oracle.rb +0 -159
  269. data/lib/arel/visitors/oracle12.rb +0 -66
  270. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -19,6 +19,10 @@ module ActiveRecord
19
19
  def readonly_attributes
20
20
  _attr_readonly
21
21
  end
22
+
23
+ def readonly_attribute?(name) # :nodoc:
24
+ _attr_readonly.include?(name)
25
+ end
22
26
  end
23
27
  end
24
28
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/string/filters"
4
- require "concurrent/map"
5
4
 
6
5
  module ActiveRecord
7
6
  # = Active Record Reflection
@@ -163,13 +162,7 @@ module ActiveRecord
163
162
  # <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
164
163
  # <tt>has_many :clients</tt> returns <tt>'Client'</tt>
165
164
  def class_name
166
- @class_name ||= (options[:class_name] || derive_class_name).to_s
167
- end
168
-
169
- JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
170
-
171
- def join_keys
172
- @join_keys ||= get_join_keys(klass)
165
+ @class_name ||= -(options[:class_name] || derive_class_name).to_s
173
166
  end
174
167
 
175
168
  # Returns a list of scopes that should be applied for this Reflection
@@ -183,25 +176,27 @@ module ActiveRecord
183
176
  scope_chain_items = join_scopes(table, predicate_builder)
184
177
  klass_scope = klass_join_scope(table, predicate_builder)
185
178
 
186
- key = join_keys.key
187
- foreign_key = join_keys.foreign_key
188
-
189
- klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
190
-
191
179
  if type
192
180
  klass_scope.where!(type => foreign_klass.polymorphic_name)
193
181
  end
194
182
 
183
+ scope_chain_items.inject(klass_scope, &:merge!)
184
+
185
+ primary_key = join_primary_key
186
+ foreign_key = join_foreign_key
187
+
188
+ klass_scope.where!(table[primary_key].eq(foreign_table[foreign_key]))
189
+
195
190
  if klass.finder_needs_type_condition?
196
191
  klass_scope.where!(klass.send(:type_condition, table))
197
192
  end
198
193
 
199
- scope_chain_items.inject(klass_scope, &:merge!)
194
+ klass_scope
200
195
  end
201
196
 
202
- def join_scopes(table, predicate_builder) # :nodoc:
197
+ def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
203
198
  if scope
204
- [scope_for(build_scope(table, predicate_builder))]
199
+ [scope_for(build_scope(table, predicate_builder, klass))]
205
200
  else
206
201
  []
207
202
  end
@@ -217,14 +212,14 @@ module ActiveRecord
217
212
  end
218
213
 
219
214
  def counter_cache_column
220
- if belongs_to?
215
+ @counter_cache_column ||= if belongs_to?
221
216
  if options[:counter_cache] == true
222
- "#{active_record.name.demodulize.underscore.pluralize}_count"
217
+ -"#{active_record.name.demodulize.underscore.pluralize}_count"
223
218
  elsif options[:counter_cache]
224
- options[:counter_cache].to_s
219
+ -options[:counter_cache].to_s
225
220
  end
226
221
  else
227
- options[:counter_cache] ? options[:counter_cache].to_s : "#{name}_count"
222
+ -(options[:counter_cache]&.to_s || "#{name}_count")
228
223
  end
229
224
  end
230
225
 
@@ -271,7 +266,7 @@ module ActiveRecord
271
266
  def has_cached_counter?
272
267
  options[:counter_cache] ||
273
268
  inverse_which_updates_counter_cache && inverse_which_updates_counter_cache.options[:counter_cache] &&
274
- !!active_record.columns_hash[counter_cache_column]
269
+ active_record.has_attribute?(counter_cache_column)
275
270
  end
276
271
 
277
272
  def counter_must_be_updated_by_has_many?
@@ -286,11 +281,7 @@ module ActiveRecord
286
281
  collect_join_chain
287
282
  end
288
283
 
289
- def get_join_keys(association_klass)
290
- JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
291
- end
292
-
293
- def build_scope(table, predicate_builder = predicate_builder(table))
284
+ def build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass)
294
285
  Relation.create(
295
286
  klass,
296
287
  table: table,
@@ -298,12 +289,8 @@ module ActiveRecord
298
289
  )
299
290
  end
300
291
 
301
- def join_primary_key(*)
302
- foreign_key
303
- end
304
-
305
- def join_foreign_key
306
- active_record_primary_key
292
+ def strict_loading?
293
+ options[:strict_loading]
307
294
  end
308
295
 
309
296
  protected
@@ -427,22 +414,21 @@ module ActiveRecord
427
414
 
428
415
  def initialize(name, scope, options, active_record)
429
416
  super
430
- @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
431
- @foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
417
+ @type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
418
+ @foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]
432
419
  @constructable = calculate_constructable(macro, options)
433
- @association_scope_cache = Concurrent::Map.new
434
420
 
435
421
  if options[:class_name] && options[:class_name].class == Class
436
422
  raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
437
423
  end
438
424
  end
439
425
 
440
- def association_scope_cache(conn, owner, &block)
441
- key = conn.prepared_statements
426
+ def association_scope_cache(klass, owner, &block)
427
+ key = self
442
428
  if polymorphic?
443
429
  key = [key, owner._read_attribute(@foreign_type)]
444
430
  end
445
- @association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
431
+ klass.cached_find_by_statement(key, &block)
446
432
  end
447
433
 
448
434
  def constructable? # :nodoc:
@@ -450,24 +436,31 @@ module ActiveRecord
450
436
  end
451
437
 
452
438
  def join_table
453
- @join_table ||= options[:join_table] || derive_join_table
439
+ @join_table ||= -(options[:join_table]&.to_s || derive_join_table)
454
440
  end
455
441
 
456
442
  def foreign_key
457
- @foreign_key ||= options[:foreign_key] || derive_foreign_key.freeze
443
+ @foreign_key ||= -(options[:foreign_key]&.to_s || derive_foreign_key)
458
444
  end
459
445
 
460
446
  def association_foreign_key
461
- @association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key
447
+ @association_foreign_key ||= -(options[:association_foreign_key]&.to_s || class_name.foreign_key)
462
448
  end
463
449
 
464
- # klass option is necessary to support loading polymorphic associations
465
450
  def association_primary_key(klass = nil)
466
- options[:primary_key] || primary_key(klass || self.klass)
451
+ primary_key(klass || self.klass)
467
452
  end
468
453
 
469
454
  def active_record_primary_key
470
- @active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
455
+ @active_record_primary_key ||= -(options[:primary_key]&.to_s || primary_key(active_record))
456
+ end
457
+
458
+ def join_primary_key(klass = nil)
459
+ foreign_key
460
+ end
461
+
462
+ def join_foreign_key
463
+ active_record_primary_key
471
464
  end
472
465
 
473
466
  def check_validity!
@@ -508,7 +501,7 @@ module ActiveRecord
508
501
  # This is for clearing cache on the reflection. Useful for tests that need to compare
509
502
  # SQL queries on associations.
510
503
  def clear_association_scope_cache # :nodoc:
511
- @association_scope_cache.clear
504
+ klass.initialize_find_by_cache
512
505
  end
513
506
 
514
507
  def nested?
@@ -590,7 +583,6 @@ module ActiveRecord
590
583
  end
591
584
 
592
585
  private
593
-
594
586
  def calculate_constructable(macro, options)
595
587
  true
596
588
  end
@@ -620,7 +612,7 @@ module ActiveRecord
620
612
  end
621
613
 
622
614
  if valid_inverse_reflection?(reflection)
623
- return inverse_name
615
+ inverse_name
624
616
  end
625
617
  end
626
618
  end
@@ -631,6 +623,7 @@ module ActiveRecord
631
623
  # with the current reflection's klass name.
632
624
  def valid_inverse_reflection?(reflection)
633
625
  reflection &&
626
+ foreign_key == reflection.foreign_key &&
634
627
  klass <= reflection.active_record &&
635
628
  can_find_inverse_of_automatically?(reflection)
636
629
  end
@@ -684,10 +677,6 @@ module ActiveRecord
684
677
  Associations::HasManyAssociation
685
678
  end
686
679
  end
687
-
688
- def association_primary_key(klass = nil)
689
- primary_key(klass || self.klass)
690
- end
691
680
  end
692
681
 
693
682
  class HasOneReflection < AssociationReflection # :nodoc:
@@ -704,7 +693,6 @@ module ActiveRecord
704
693
  end
705
694
 
706
695
  private
707
-
708
696
  def calculate_constructable(macro, options)
709
697
  !options[:through]
710
698
  end
@@ -723,6 +711,15 @@ module ActiveRecord
723
711
  end
724
712
  end
725
713
 
714
+ # klass option is necessary to support loading polymorphic associations
715
+ def association_primary_key(klass = nil)
716
+ if primary_key = options[:primary_key]
717
+ @association_primary_key ||= -primary_key.to_s
718
+ else
719
+ primary_key(klass || self.klass)
720
+ end
721
+ end
722
+
726
723
  def join_primary_key(klass = nil)
727
724
  polymorphic? ? association_primary_key(klass) : association_primary_key
728
725
  end
@@ -731,6 +728,10 @@ module ActiveRecord
731
728
  foreign_key
732
729
  end
733
730
 
731
+ def join_foreign_type
732
+ foreign_type
733
+ end
734
+
734
735
  private
735
736
  def can_find_inverse_of_automatically?(_)
736
737
  !polymorphic? && super
@@ -752,8 +753,8 @@ module ActiveRecord
752
753
  # Holds all the metadata about a :through association as it was specified
753
754
  # in the Active Record class.
754
755
  class ThroughReflection < AbstractReflection #:nodoc:
755
- delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
756
- :active_record_primary_key, :type, :get_join_keys, to: :source_reflection
756
+ delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type,
757
+ :active_record_primary_key, :join_foreign_key, to: :source_reflection
757
758
 
758
759
  def initialize(delegate_reflection)
759
760
  @delegate_reflection = delegate_reflection
@@ -839,8 +840,8 @@ module ActiveRecord
839
840
  source_reflection.scopes + super
840
841
  end
841
842
 
842
- def join_scopes(table, predicate_builder) # :nodoc:
843
- source_reflection.join_scopes(table, predicate_builder) + super
843
+ def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
844
+ source_reflection.join_scopes(table, predicate_builder, klass) + super
844
845
  end
845
846
 
846
847
  def has_scope?
@@ -860,7 +861,15 @@ module ActiveRecord
860
861
  def association_primary_key(klass = nil)
861
862
  # Get the "actual" source reflection if the immediate source reflection has a
862
863
  # source reflection itself
863
- actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
864
+ if primary_key = actual_source_reflection.options[:primary_key]
865
+ @association_primary_key ||= -primary_key.to_s
866
+ else
867
+ primary_key(klass || self.klass)
868
+ end
869
+ end
870
+
871
+ def join_primary_key(klass = self.klass)
872
+ source_reflection.join_primary_key(klass)
864
873
  end
865
874
 
866
875
  # Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
@@ -909,7 +918,7 @@ module ActiveRecord
909
918
 
910
919
  def check_validity!
911
920
  if through_reflection.nil?
912
- raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
921
+ raise HasManyThroughAssociationNotFoundError.new(active_record, self)
913
922
  end
914
923
 
915
924
  if through_reflection.polymorphic?
@@ -996,16 +1005,17 @@ module ActiveRecord
996
1005
  end
997
1006
 
998
1007
  class PolymorphicReflection < AbstractReflection # :nodoc:
999
- delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
1008
+ delegate :klass, :scope, :plural_name, :type, :join_primary_key, :join_foreign_key,
1009
+ :name, :scope_for, to: :@reflection
1000
1010
 
1001
1011
  def initialize(reflection, previous_reflection)
1002
1012
  @reflection = reflection
1003
1013
  @previous_reflection = previous_reflection
1004
1014
  end
1005
1015
 
1006
- def join_scopes(table, predicate_builder) # :nodoc:
1016
+ def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
1007
1017
  scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
1008
- scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
1018
+ scopes << build_scope(table, predicate_builder, klass).instance_exec(nil, &source_type_scope)
1009
1019
  end
1010
1020
 
1011
1021
  def constraints
@@ -1021,7 +1031,7 @@ module ActiveRecord
1021
1031
  end
1022
1032
 
1023
1033
  class RuntimeReflection < AbstractReflection # :nodoc:
1024
- delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
1034
+ delegate :scope, :type, :constraints, :join_foreign_key, to: :@reflection
1025
1035
 
1026
1036
  def initialize(reflection, association)
1027
1037
  @reflection = reflection
@@ -1033,7 +1043,11 @@ module ActiveRecord
1033
1043
  end
1034
1044
 
1035
1045
  def aliased_table
1036
- @aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
1046
+ klass.arel_table
1047
+ end
1048
+
1049
+ def join_primary_key(klass = self.klass)
1050
+ @reflection.join_primary_key(klass)
1037
1051
  end
1038
1052
 
1039
1053
  def all_includes; yield; end
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  :order, :joins, :left_outer_joins, :references,
8
8
  :extending, :unscope, :optimizer_hints, :annotate]
9
9
 
10
- SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering,
10
+ SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering, :strict_loading,
11
11
  :reverse_order, :distinct, :create_with, :skip_query_cache]
12
12
 
13
13
  CLAUSE_METHODS = [:where, :having, :from]
@@ -28,7 +28,6 @@ module ActiveRecord
28
28
  @klass = klass
29
29
  @table = table
30
30
  @values = values
31
- @offsets = {}
32
31
  @loaded = false
33
32
  @predicate_builder = predicate_builder
34
33
  @delegate_to_klass = false
@@ -40,8 +39,9 @@ module ActiveRecord
40
39
  end
41
40
 
42
41
  def arel_attribute(name) # :nodoc:
43
- klass.arel_attribute(name, table)
42
+ table[name]
44
43
  end
44
+ deprecate :arel_attribute
45
45
 
46
46
  def bind_attribute(name, value) # :nodoc:
47
47
  if reflection = klass._reflect_on_association(name)
@@ -49,7 +49,7 @@ module ActiveRecord
49
49
  value = value.read_attribute(reflection.klass.primary_key) unless value.nil?
50
50
  end
51
51
 
52
- attr = arel_attribute(name)
52
+ attr = table[name]
53
53
  bind = predicate_builder.build_bind_attribute(attr.name, value)
54
54
  yield attr, bind
55
55
  end
@@ -67,10 +67,9 @@ module ActiveRecord
67
67
  # user = users.new { |user| user.name = 'Oscar' }
68
68
  # user.name # => Oscar
69
69
  def new(attributes = nil, &block)
70
- block = _deprecated_scope_block("new", &block)
71
- scoping { klass.new(attributes, &block) }
70
+ block = current_scope_restoring_block(&block)
71
+ scoping { _new(attributes, &block) }
72
72
  end
73
-
74
73
  alias build new
75
74
 
76
75
  # Tries to create a new record with the same scoped attributes
@@ -96,8 +95,8 @@ module ActiveRecord
96
95
  if attributes.is_a?(Array)
97
96
  attributes.collect { |attr| create(attr, &block) }
98
97
  else
99
- block = _deprecated_scope_block("create", &block)
100
- scoping { klass.create(attributes, &block) }
98
+ block = current_scope_restoring_block(&block)
99
+ scoping { _create(attributes, &block) }
101
100
  end
102
101
  end
103
102
 
@@ -111,8 +110,8 @@ module ActiveRecord
111
110
  if attributes.is_a?(Array)
112
111
  attributes.collect { |attr| create!(attr, &block) }
113
112
  else
114
- block = _deprecated_scope_block("create!", &block)
115
- scoping { klass.create!(attributes, &block) }
113
+ block = current_scope_restoring_block(&block)
114
+ scoping { _create!(attributes, &block) }
116
115
  end
117
116
  end
118
117
 
@@ -308,7 +307,7 @@ module ActiveRecord
308
307
  # last updated record.
309
308
  #
310
309
  # Product.where("name like ?", "%Game%").cache_key(:last_reviewed_at)
311
- def cache_key(timestamp_column = :updated_at)
310
+ def cache_key(timestamp_column = "updated_at")
312
311
  @cache_keys ||= {}
313
312
  @cache_keys[timestamp_column] ||= klass.collection_cache_key(self, timestamp_column)
314
313
  end
@@ -317,7 +316,7 @@ module ActiveRecord
317
316
  query_signature = ActiveSupport::Digest.hexdigest(to_sql)
318
317
  key = "#{klass.model_name.cache_key}/query-#{query_signature}"
319
318
 
320
- if cache_version(timestamp_column)
319
+ if collection_cache_versioning
321
320
  key
322
321
  else
323
322
  "#{key}-#{compute_cache_version(timestamp_column)}"
@@ -343,15 +342,17 @@ module ActiveRecord
343
342
  end
344
343
 
345
344
  def compute_cache_version(timestamp_column) # :nodoc:
345
+ timestamp_column = timestamp_column.to_s
346
+
346
347
  if loaded? || distinct_value
347
348
  size = records.size
348
349
  if size > 0
349
- timestamp = max_by(&timestamp_column)._read_attribute(timestamp_column)
350
+ timestamp = records.map { |record| record.read_attribute(timestamp_column) }.max
350
351
  end
351
352
  else
352
353
  collection = eager_loading? ? apply_join_dependency : self
353
354
 
354
- column = connection.visitor.compile(arel_attribute(timestamp_column))
355
+ column = connection.visitor.compile(table[timestamp_column])
355
356
  select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp"
356
357
 
357
358
  if collection.has_limit_or_offset?
@@ -365,14 +366,12 @@ module ActiveRecord
365
366
  arel = query.arel
366
367
  end
367
368
 
368
- result = connection.select_one(arel, nil)
369
+ size, timestamp = connection.select_rows(arel, nil).first
369
370
 
370
- if result
371
+ if size
371
372
  column_type = klass.type_for_attribute(timestamp_column)
372
- timestamp = column_type.deserialize(result["timestamp"])
373
- size = result["size"]
373
+ timestamp = column_type.deserialize(timestamp)
374
374
  else
375
- timestamp = nil
376
375
  size = 0
377
376
  end
378
377
  end
@@ -385,6 +384,15 @@ module ActiveRecord
385
384
  end
386
385
  private :compute_cache_version
387
386
 
387
+ # Returns a cache key along with the version.
388
+ def cache_key_with_version
389
+ if version = cache_version
390
+ "#{cache_key}-#{version}"
391
+ else
392
+ cache_key
393
+ end
394
+ end
395
+
388
396
  # Scope all queries to the current scope.
389
397
  #
390
398
  # Comment.where(post_id: 1).scoping do
@@ -398,9 +406,9 @@ module ActiveRecord
398
406
  already_in_scope? ? yield : _scoping(self) { yield }
399
407
  end
400
408
 
401
- def _exec_scope(name, *args, &block) # :nodoc:
409
+ def _exec_scope(*args, &block) # :nodoc:
402
410
  @delegate_to_klass = true
403
- _scoping(_deprecated_spawn(name)) { instance_exec(*args, &block) || self }
411
+ _scoping(nil) { instance_exec(*args, &block) || self }
404
412
  ensure
405
413
  @delegate_to_klass = false
406
414
  end
@@ -408,7 +416,7 @@ module ActiveRecord
408
416
  # Updates all records in the current relation with details given. This method constructs a single SQL UPDATE
409
417
  # statement and sends it straight to the database. It does not instantiate the involved models and it does not
410
418
  # trigger Active Record callbacks or validations. However, values passed to #update_all will still go through
411
- # Active Record's normal type casting and serialization.
419
+ # Active Record's normal type casting and serialization. Returns the number of rows affected.
412
420
  #
413
421
  # Note: As Active Record callbacks are not triggered, this method will not automatically update +updated_at+/+updated_on+ columns.
414
422
  #
@@ -439,7 +447,7 @@ module ActiveRecord
439
447
 
440
448
  stmt = Arel::UpdateManager.new
441
449
  stmt.table(arel.join_sources.empty? ? table : arel.source)
442
- stmt.key = arel_attribute(primary_key)
450
+ stmt.key = table[primary_key]
443
451
  stmt.take(arel.limit)
444
452
  stmt.offset(arel.offset)
445
453
  stmt.order(*arel.orders)
@@ -449,7 +457,7 @@ module ActiveRecord
449
457
  if klass.locking_enabled? &&
450
458
  !updates.key?(klass.locking_column) &&
451
459
  !updates.key?(klass.locking_column.to_sym)
452
- attr = arel_attribute(klass.locking_column)
460
+ attr = table[klass.locking_column]
453
461
  updates[attr.name] = _increment_attribute(attr)
454
462
  end
455
463
  stmt.set _substitute_values(updates)
@@ -468,26 +476,40 @@ module ActiveRecord
468
476
  end
469
477
  end
470
478
 
471
- def update_counters(counters) # :nodoc:
479
+ # Updates the counters of the records in the current relation.
480
+ #
481
+ # ==== Parameters
482
+ #
483
+ # * +counter+ - A Hash containing the names of the fields to update as keys and the amount to update as values.
484
+ # * <tt>:touch</tt> option - Touch the timestamp columns when updating.
485
+ # * If attributes names are passed, they are updated along with update_at/on attributes.
486
+ #
487
+ # ==== Examples
488
+ #
489
+ # # For Posts by a given author increment the comment_count by 1.
490
+ # Post.where(author_id: author.id).update_counters(comment_count: 1)
491
+ def update_counters(counters)
472
492
  touch = counters.delete(:touch)
473
493
 
474
494
  updates = {}
475
495
  counters.each do |counter_name, value|
476
- attr = arel_attribute(counter_name)
496
+ attr = table[counter_name]
477
497
  updates[attr.name] = _increment_attribute(attr, value)
478
498
  end
479
499
 
480
500
  if touch
481
501
  names = touch if touch != true
482
- touch_updates = klass.touch_attributes_with_time(*names)
502
+ names = Array.wrap(names)
503
+ options = names.extract_options!
504
+ touch_updates = klass.touch_attributes_with_time(*names, **options)
483
505
  updates.merge!(touch_updates) unless touch_updates.empty?
484
506
  end
485
507
 
486
508
  update_all updates
487
509
  end
488
510
 
489
- # Touches all records in the current relation without instantiating records first with the +updated_at+/+updated_on+ attributes
490
- # set to the current time or the time specified.
511
+ # Touches all records in the current relation, setting the +updated_at+/+updated_on+ attributes to the current time or the time specified.
512
+ # It does not instantiate the involved models, and it does not trigger Active Record callbacks or validations.
491
513
  # This method can be passed attribute names and an optional time argument.
492
514
  # If attribute names are passed, they are updated along with +updated_at+/+updated_on+ attributes.
493
515
  # If no time argument is passed, the current time is used as default.
@@ -567,7 +589,7 @@ module ActiveRecord
567
589
 
568
590
  stmt = Arel::DeleteManager.new
569
591
  stmt.from(arel.join_sources.empty? ? table : arel.source)
570
- stmt.key = arel_attribute(primary_key)
592
+ stmt.key = table[primary_key]
571
593
  stmt.take(arel.limit)
572
594
  stmt.offset(arel.offset)
573
595
  stmt.order(*arel.orders)
@@ -612,7 +634,10 @@ module ActiveRecord
612
634
  #
613
635
  # Post.where(published: true).load # => #<ActiveRecord::Relation>
614
636
  def load(&block)
615
- exec_queries(&block) unless loaded?
637
+ unless loaded?
638
+ @records = exec_queries(&block)
639
+ @loaded = true
640
+ end
616
641
 
617
642
  self
618
643
  end
@@ -625,10 +650,9 @@ module ActiveRecord
625
650
 
626
651
  def reset
627
652
  @delegate_to_klass = false
628
- @_deprecated_scope_source = nil
629
653
  @to_sql = @arel = @loaded = @should_eager_load = nil
654
+ @offsets = @take = nil
630
655
  @records = [].freeze
631
- @offsets = {}
632
656
  self
633
657
  end
634
658
 
@@ -659,7 +683,9 @@ module ActiveRecord
659
683
  end
660
684
 
661
685
  def scope_for_create
662
- where_values_hash.merge!(create_with_value.stringify_keys)
686
+ hash = where_clause.to_h(klass.table_name, equality_only: true)
687
+ create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
688
+ hash
663
689
  end
664
690
 
665
691
  # Returns true if relation needs eager loading.
@@ -703,7 +729,7 @@ module ActiveRecord
703
729
  end
704
730
 
705
731
  def inspect
706
- subject = loaded? ? records : self
732
+ subject = loaded? ? records : annotate("loading for inspect")
707
733
  entries = subject.take([limit_value, 11].compact.min).map!(&:inspect)
708
734
 
709
735
  entries[10] = "..." if entries.size == 11
@@ -720,25 +746,31 @@ module ActiveRecord
720
746
  end
721
747
 
722
748
  def alias_tracker(joins = [], aliases = nil) # :nodoc:
723
- joins += [aliases] if aliases
724
- ActiveRecord::Associations::AliasTracker.create(connection, table.name, joins)
749
+ ActiveRecord::Associations::AliasTracker.create(connection, table.name, joins, aliases)
750
+ end
751
+
752
+ class StrictLoadingScope # :nodoc:
753
+ def self.empty_scope?
754
+ true
755
+ end
756
+
757
+ def self.strict_loading_value
758
+ true
759
+ end
725
760
  end
726
761
 
727
762
  def preload_associations(records) # :nodoc:
728
763
  preload = preload_values
729
764
  preload += includes_values unless eager_loading?
730
765
  preloader = nil
766
+ scope = strict_loading_value ? StrictLoadingScope : nil
731
767
  preload.each do |associations|
732
768
  preloader ||= build_preloader
733
- preloader.preload records, associations
769
+ preloader.preload records, associations, scope
734
770
  end
735
771
  end
736
772
 
737
- attr_reader :_deprecated_scope_source # :nodoc:
738
-
739
773
  protected
740
- attr_writer :_deprecated_scope_source # :nodoc:
741
-
742
774
  def load_records(records)
743
775
  @records = records.freeze
744
776
  @loaded = true
@@ -750,23 +782,29 @@ module ActiveRecord
750
782
 
751
783
  private
752
784
  def already_in_scope?
753
- @delegate_to_klass && begin
754
- scope = klass.current_scope(true)
755
- scope && !scope._deprecated_scope_source
756
- end
785
+ @delegate_to_klass && klass.current_scope(true)
757
786
  end
758
787
 
759
- def _deprecated_spawn(name)
760
- spawn.tap { |scope| scope._deprecated_scope_source = name }
761
- end
762
-
763
- def _deprecated_scope_block(name, &block)
788
+ def current_scope_restoring_block(&block)
789
+ current_scope = klass.current_scope(true)
764
790
  -> record do
765
- klass.current_scope = _deprecated_spawn(name)
791
+ klass.current_scope = current_scope
766
792
  yield record if block_given?
767
793
  end
768
794
  end
769
795
 
796
+ def _new(attributes, &block)
797
+ klass.new(attributes, &block)
798
+ end
799
+
800
+ def _create(attributes, &block)
801
+ klass.create(attributes, &block)
802
+ end
803
+
804
+ def _create!(attributes, &block)
805
+ klass.create!(attributes, &block)
806
+ end
807
+
770
808
  def _scoping(scope)
771
809
  previous, klass.current_scope = klass.current_scope(true), scope
772
810
  yield
@@ -776,7 +814,7 @@ module ActiveRecord
776
814
 
777
815
  def _substitute_values(values)
778
816
  values.map do |name, value|
779
- attr = arel_attribute(name)
817
+ attr = table[name]
780
818
  unless Arel.arel_node?(value)
781
819
  type = klass.type_for_attribute(attr.name)
782
820
  value = predicate_builder.build_bind_attribute(attr.name, type.cast(value))
@@ -794,27 +832,29 @@ module ActiveRecord
794
832
 
795
833
  def exec_queries(&block)
796
834
  skip_query_cache_if_necessary do
797
- @records =
798
- if eager_loading?
835
+ records =
836
+ if where_clause.contradiction?
837
+ []
838
+ elsif eager_loading?
799
839
  apply_join_dependency do |relation, join_dependency|
800
840
  if relation.null_relation?
801
841
  []
802
842
  else
803
843
  relation = join_dependency.apply_column_aliases(relation)
804
844
  rows = connection.select_all(relation.arel, "SQL")
805
- join_dependency.instantiate(rows, &block)
845
+ join_dependency.instantiate(rows, strict_loading_value, &block)
806
846
  end.freeze
807
847
  end
808
848
  else
809
849
  klass.find_by_sql(arel, &block).freeze
810
850
  end
811
851
 
812
- preload_associations(@records) unless skip_preloading_value
852
+ preload_associations(records) unless skip_preloading_value
813
853
 
814
- @records.each(&:readonly!) if readonly_value
854
+ records.each(&:readonly!) if readonly_value
855
+ records.each(&:strict_loading!) if strict_loading_value
815
856
 
816
- @loaded = true
817
- @records
857
+ records
818
858
  end
819
859
  end
820
860
 
@@ -833,27 +873,27 @@ module ActiveRecord
833
873
  end
834
874
 
835
875
  def references_eager_loaded_tables?
836
- joined_tables = arel.join_sources.map do |join|
876
+ joined_tables = build_joins([]).flat_map do |join|
837
877
  if join.is_a?(Arel::Nodes::StringJoin)
838
878
  tables_in_string(join.left)
839
879
  else
840
- [join.left.table_name, join.left.table_alias]
880
+ join.left.name
841
881
  end
842
882
  end
843
883
 
844
- joined_tables += [table.name, table.table_alias]
884
+ joined_tables << table.name
845
885
 
846
886
  # always convert table names to downcase as in Oracle quoted table names are in uppercase
847
- joined_tables = joined_tables.flatten.compact.map(&:downcase).uniq
887
+ joined_tables.map!(&:downcase)
848
888
 
849
- (references_values - joined_tables).any?
889
+ !(references_values.map(&:to_s) - joined_tables).empty?
850
890
  end
851
891
 
852
892
  def tables_in_string(string)
853
893
  return [] if string.blank?
854
894
  # always convert table names to downcase as in Oracle quoted table names are in uppercase
855
895
  # ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
856
- string.scan(/([a-zA-Z_][.\w]+).?\./).flatten.map(&:downcase).uniq - ["raw_sql_"]
896
+ string.scan(/[a-zA-Z_][.\w]+(?=.?\.)/).map!(&:downcase) - ["raw_sql_"]
857
897
  end
858
898
  end
859
899
  end