activerecord 6.1.7 → 7.1.0

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.
Files changed (307) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1516 -1019
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +17 -18
  5. data/lib/active_record/aggregations.rb +17 -14
  6. data/lib/active_record/association_relation.rb +1 -11
  7. data/lib/active_record/associations/association.rb +50 -19
  8. data/lib/active_record/associations/association_scope.rb +17 -12
  9. data/lib/active_record/associations/belongs_to_association.rb +28 -9
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
  11. data/lib/active_record/associations/builder/association.rb +11 -5
  12. data/lib/active_record/associations/builder/belongs_to.rb +40 -14
  13. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  14. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
  15. data/lib/active_record/associations/builder/has_many.rb +3 -2
  16. data/lib/active_record/associations/builder/has_one.rb +2 -1
  17. data/lib/active_record/associations/builder/singular_association.rb +6 -2
  18. data/lib/active_record/associations/collection_association.rb +35 -31
  19. data/lib/active_record/associations/collection_proxy.rb +30 -15
  20. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  21. data/lib/active_record/associations/foreign_association.rb +10 -3
  22. data/lib/active_record/associations/has_many_association.rb +28 -18
  23. data/lib/active_record/associations/has_many_through_association.rb +12 -7
  24. data/lib/active_record/associations/has_one_association.rb +20 -10
  25. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  26. data/lib/active_record/associations/join_dependency.rb +26 -16
  27. data/lib/active_record/associations/preloader/association.rb +207 -52
  28. data/lib/active_record/associations/preloader/batch.rb +48 -0
  29. data/lib/active_record/associations/preloader/branch.rb +147 -0
  30. data/lib/active_record/associations/preloader/through_association.rb +50 -14
  31. data/lib/active_record/associations/preloader.rb +50 -121
  32. data/lib/active_record/associations/singular_association.rb +9 -3
  33. data/lib/active_record/associations/through_association.rb +25 -14
  34. data/lib/active_record/associations.rb +423 -289
  35. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  36. data/lib/active_record/attribute_assignment.rb +1 -3
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
  38. data/lib/active_record/attribute_methods/dirty.rb +61 -14
  39. data/lib/active_record/attribute_methods/primary_key.rb +78 -26
  40. data/lib/active_record/attribute_methods/query.rb +31 -19
  41. data/lib/active_record/attribute_methods/read.rb +25 -10
  42. data/lib/active_record/attribute_methods/serialization.rb +194 -37
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
  44. data/lib/active_record/attribute_methods/write.rb +10 -13
  45. data/lib/active_record/attribute_methods.rb +121 -40
  46. data/lib/active_record/attributes.rb +27 -38
  47. data/lib/active_record/autosave_association.rb +61 -30
  48. data/lib/active_record/base.rb +25 -2
  49. data/lib/active_record/callbacks.rb +18 -34
  50. data/lib/active_record/coders/column_serializer.rb +61 -0
  51. data/lib/active_record/coders/json.rb +1 -1
  52. data/lib/active_record/coders/yaml_column.rb +70 -46
  53. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
  54. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  55. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +96 -590
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +171 -51
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +77 -27
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +360 -136
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +622 -149
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +285 -156
  69. data/lib/active_record/connection_adapters/column.rb +13 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
  72. data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
  73. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  75. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  76. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
  77. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
  78. data/lib/active_record/connection_adapters/mysql2_adapter.rb +104 -53
  79. data/lib/active_record/connection_adapters/pool_config.rb +20 -11
  80. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +18 -1
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +86 -52
  83. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  87. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
  88. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  91. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +381 -69
  98. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  99. data/lib/active_record/connection_adapters/postgresql_adapter.rb +492 -230
  100. data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
  101. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  102. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +65 -53
  103. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
  104. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
  105. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +294 -102
  107. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  108. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
  109. data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
  110. data/lib/active_record/connection_adapters.rb +9 -6
  111. data/lib/active_record/connection_handling.rb +107 -136
  112. data/lib/active_record/core.rb +194 -224
  113. data/lib/active_record/counter_cache.rb +46 -25
  114. data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
  115. data/lib/active_record/database_configurations/database_config.rb +21 -12
  116. data/lib/active_record/database_configurations/hash_config.rb +84 -16
  117. data/lib/active_record/database_configurations/url_config.rb +18 -12
  118. data/lib/active_record/database_configurations.rb +95 -59
  119. data/lib/active_record/delegated_type.rb +61 -15
  120. data/lib/active_record/deprecator.rb +7 -0
  121. data/lib/active_record/destroy_association_async_job.rb +3 -1
  122. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  123. data/lib/active_record/dynamic_matchers.rb +1 -1
  124. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  125. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  126. data/lib/active_record/encryption/cipher.rb +53 -0
  127. data/lib/active_record/encryption/config.rb +68 -0
  128. data/lib/active_record/encryption/configurable.rb +60 -0
  129. data/lib/active_record/encryption/context.rb +42 -0
  130. data/lib/active_record/encryption/contexts.rb +76 -0
  131. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  132. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  133. data/lib/active_record/encryption/encryptable_record.rb +224 -0
  134. data/lib/active_record/encryption/encrypted_attribute_type.rb +151 -0
  135. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  136. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  137. data/lib/active_record/encryption/encryptor.rb +155 -0
  138. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  139. data/lib/active_record/encryption/errors.rb +15 -0
  140. data/lib/active_record/encryption/extended_deterministic_queries.rb +172 -0
  141. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  142. data/lib/active_record/encryption/key.rb +28 -0
  143. data/lib/active_record/encryption/key_generator.rb +53 -0
  144. data/lib/active_record/encryption/key_provider.rb +46 -0
  145. data/lib/active_record/encryption/message.rb +33 -0
  146. data/lib/active_record/encryption/message_serializer.rb +92 -0
  147. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  148. data/lib/active_record/encryption/properties.rb +76 -0
  149. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  150. data/lib/active_record/encryption/scheme.rb +96 -0
  151. data/lib/active_record/encryption.rb +56 -0
  152. data/lib/active_record/enum.rb +156 -62
  153. data/lib/active_record/errors.rb +171 -15
  154. data/lib/active_record/explain.rb +23 -3
  155. data/lib/active_record/explain_registry.rb +11 -6
  156. data/lib/active_record/explain_subscriber.rb +1 -1
  157. data/lib/active_record/fixture_set/file.rb +15 -1
  158. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  159. data/lib/active_record/fixture_set/render_context.rb +2 -0
  160. data/lib/active_record/fixture_set/table_row.rb +70 -14
  161. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  162. data/lib/active_record/fixtures.rb +131 -86
  163. data/lib/active_record/future_result.rb +164 -0
  164. data/lib/active_record/gem_version.rb +3 -3
  165. data/lib/active_record/inheritance.rb +81 -29
  166. data/lib/active_record/insert_all.rb +133 -20
  167. data/lib/active_record/integration.rb +11 -10
  168. data/lib/active_record/internal_metadata.rb +117 -33
  169. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  170. data/lib/active_record/locking/optimistic.rb +36 -21
  171. data/lib/active_record/locking/pessimistic.rb +15 -6
  172. data/lib/active_record/log_subscriber.rb +52 -19
  173. data/lib/active_record/marshalling.rb +56 -0
  174. data/lib/active_record/message_pack.rb +124 -0
  175. data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
  176. data/lib/active_record/middleware/database_selector.rb +23 -13
  177. data/lib/active_record/middleware/shard_selector.rb +62 -0
  178. data/lib/active_record/migration/command_recorder.rb +108 -13
  179. data/lib/active_record/migration/compatibility.rb +221 -48
  180. data/lib/active_record/migration/default_strategy.rb +23 -0
  181. data/lib/active_record/migration/execution_strategy.rb +19 -0
  182. data/lib/active_record/migration/join_table.rb +1 -1
  183. data/lib/active_record/migration.rb +355 -171
  184. data/lib/active_record/model_schema.rb +116 -97
  185. data/lib/active_record/nested_attributes.rb +36 -15
  186. data/lib/active_record/no_touching.rb +3 -3
  187. data/lib/active_record/normalization.rb +159 -0
  188. data/lib/active_record/persistence.rb +405 -85
  189. data/lib/active_record/promise.rb +84 -0
  190. data/lib/active_record/query_cache.rb +3 -21
  191. data/lib/active_record/query_logs.rb +174 -0
  192. data/lib/active_record/query_logs_formatter.rb +41 -0
  193. data/lib/active_record/querying.rb +29 -6
  194. data/lib/active_record/railtie.rb +219 -43
  195. data/lib/active_record/railties/controller_runtime.rb +13 -9
  196. data/lib/active_record/railties/databases.rake +185 -249
  197. data/lib/active_record/railties/job_runtime.rb +23 -0
  198. data/lib/active_record/readonly_attributes.rb +41 -3
  199. data/lib/active_record/reflection.rb +229 -80
  200. data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
  201. data/lib/active_record/relation/batches.rb +192 -63
  202. data/lib/active_record/relation/calculations.rb +211 -90
  203. data/lib/active_record/relation/delegation.rb +27 -13
  204. data/lib/active_record/relation/finder_methods.rb +108 -51
  205. data/lib/active_record/relation/merger.rb +22 -13
  206. data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
  207. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
  208. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  209. data/lib/active_record/relation/predicate_builder.rb +27 -20
  210. data/lib/active_record/relation/query_attribute.rb +30 -12
  211. data/lib/active_record/relation/query_methods.rb +654 -127
  212. data/lib/active_record/relation/record_fetch_warning.rb +7 -9
  213. data/lib/active_record/relation/spawn_methods.rb +20 -3
  214. data/lib/active_record/relation/where_clause.rb +10 -19
  215. data/lib/active_record/relation.rb +262 -120
  216. data/lib/active_record/result.rb +37 -11
  217. data/lib/active_record/runtime_registry.rb +18 -13
  218. data/lib/active_record/sanitization.rb +65 -20
  219. data/lib/active_record/schema.rb +36 -22
  220. data/lib/active_record/schema_dumper.rb +73 -24
  221. data/lib/active_record/schema_migration.rb +68 -33
  222. data/lib/active_record/scoping/default.rb +72 -15
  223. data/lib/active_record/scoping/named.rb +5 -13
  224. data/lib/active_record/scoping.rb +65 -34
  225. data/lib/active_record/secure_password.rb +60 -0
  226. data/lib/active_record/secure_token.rb +21 -3
  227. data/lib/active_record/serialization.rb +6 -1
  228. data/lib/active_record/signed_id.rb +10 -8
  229. data/lib/active_record/store.rb +10 -10
  230. data/lib/active_record/suppressor.rb +13 -15
  231. data/lib/active_record/table_metadata.rb +16 -3
  232. data/lib/active_record/tasks/database_tasks.rb +225 -136
  233. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
  234. data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
  235. data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
  236. data/lib/active_record/test_databases.rb +1 -1
  237. data/lib/active_record/test_fixtures.rb +116 -96
  238. data/lib/active_record/timestamp.rb +28 -17
  239. data/lib/active_record/token_for.rb +113 -0
  240. data/lib/active_record/touch_later.rb +11 -6
  241. data/lib/active_record/transactions.rb +48 -27
  242. data/lib/active_record/translation.rb +3 -3
  243. data/lib/active_record/type/adapter_specific_registry.rb +32 -14
  244. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  245. data/lib/active_record/type/internal/timezone.rb +7 -2
  246. data/lib/active_record/type/serialized.rb +9 -5
  247. data/lib/active_record/type/time.rb +4 -0
  248. data/lib/active_record/type/type_map.rb +17 -20
  249. data/lib/active_record/type.rb +1 -2
  250. data/lib/active_record/validations/absence.rb +1 -1
  251. data/lib/active_record/validations/associated.rb +4 -4
  252. data/lib/active_record/validations/numericality.rb +5 -4
  253. data/lib/active_record/validations/presence.rb +5 -28
  254. data/lib/active_record/validations/uniqueness.rb +51 -6
  255. data/lib/active_record/validations.rb +8 -4
  256. data/lib/active_record/version.rb +1 -1
  257. data/lib/active_record.rb +335 -32
  258. data/lib/arel/attributes/attribute.rb +0 -8
  259. data/lib/arel/crud.rb +28 -22
  260. data/lib/arel/delete_manager.rb +18 -4
  261. data/lib/arel/errors.rb +10 -0
  262. data/lib/arel/factory_methods.rb +4 -0
  263. data/lib/arel/filter_predications.rb +9 -0
  264. data/lib/arel/insert_manager.rb +2 -3
  265. data/lib/arel/nodes/and.rb +4 -0
  266. data/lib/arel/nodes/binary.rb +6 -1
  267. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  268. data/lib/arel/nodes/casted.rb +1 -1
  269. data/lib/arel/nodes/cte.rb +36 -0
  270. data/lib/arel/nodes/delete_statement.rb +12 -13
  271. data/lib/arel/nodes/filter.rb +10 -0
  272. data/lib/arel/nodes/fragments.rb +35 -0
  273. data/lib/arel/nodes/function.rb +1 -0
  274. data/lib/arel/nodes/homogeneous_in.rb +0 -8
  275. data/lib/arel/nodes/insert_statement.rb +2 -2
  276. data/lib/arel/nodes/leading_join.rb +8 -0
  277. data/lib/arel/nodes/node.rb +111 -2
  278. data/lib/arel/nodes/select_core.rb +2 -2
  279. data/lib/arel/nodes/select_statement.rb +2 -2
  280. data/lib/arel/nodes/sql_literal.rb +6 -0
  281. data/lib/arel/nodes/table_alias.rb +4 -0
  282. data/lib/arel/nodes/update_statement.rb +8 -3
  283. data/lib/arel/nodes.rb +5 -0
  284. data/lib/arel/predications.rb +13 -3
  285. data/lib/arel/select_manager.rb +10 -4
  286. data/lib/arel/table.rb +9 -6
  287. data/lib/arel/tree_manager.rb +0 -12
  288. data/lib/arel/update_manager.rb +18 -4
  289. data/lib/arel/visitors/dot.rb +80 -90
  290. data/lib/arel/visitors/mysql.rb +16 -3
  291. data/lib/arel/visitors/postgresql.rb +0 -10
  292. data/lib/arel/visitors/to_sql.rb +139 -19
  293. data/lib/arel/visitors/visitor.rb +2 -2
  294. data/lib/arel.rb +18 -3
  295. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  296. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  297. data/lib/rails/generators/active_record/migration.rb +3 -1
  298. data/lib/rails/generators/active_record/model/USAGE +113 -0
  299. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  300. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  301. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  302. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  303. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  304. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  305. metadata +92 -13
  306. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  307. data/lib/active_record/null_relation.rb +0 -67
@@ -5,13 +5,14 @@ module ActiveRecord
5
5
  class Relation
6
6
  MULTI_VALUE_METHODS = [:includes, :eager_load, :preload, :select, :group,
7
7
  :order, :joins, :left_outer_joins, :references,
8
- :extending, :unscope, :optimizer_hints, :annotate]
8
+ :extending, :unscope, :optimizer_hints, :annotate,
9
+ :with]
9
10
 
10
11
  SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering, :strict_loading,
11
12
  :reverse_order, :distinct, :create_with, :skip_query_cache]
12
13
 
13
14
  CLAUSE_METHODS = [:where, :having, :from]
14
- INVALID_METHODS_FOR_DELETE_ALL = [:distinct, :group, :having]
15
+ INVALID_METHODS_FOR_DELETE_ALL = [:distinct, :with]
15
16
 
16
17
  VALUE_METHODS = MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS + CLAUSE_METHODS
17
18
 
@@ -31,6 +32,10 @@ module ActiveRecord
31
32
  @loaded = false
32
33
  @predicate_builder = predicate_builder
33
34
  @delegate_to_klass = false
35
+ @future_result = nil
36
+ @records = nil
37
+ @async = false
38
+ @none = false
34
39
  end
35
40
 
36
41
  def initialize_copy(other)
@@ -38,15 +43,10 @@ module ActiveRecord
38
43
  reset
39
44
  end
40
45
 
41
- def arel_attribute(name) # :nodoc:
42
- table[name]
43
- end
44
- deprecate :arel_attribute
45
-
46
46
  def bind_attribute(name, value) # :nodoc:
47
47
  if reflection = klass._reflect_on_association(name)
48
48
  name = reflection.foreign_key
49
- value = value.read_attribute(reflection.klass.primary_key) unless value.nil?
49
+ value = value.read_attribute(reflection.association_primary_key) unless value.nil?
50
50
  end
51
51
 
52
52
  attr = table[name]
@@ -67,8 +67,12 @@ 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 = current_scope_restoring_block(&block)
71
- scoping { _new(attributes, &block) }
70
+ if attributes.is_a?(Array)
71
+ attributes.collect { |attr| new(attr, &block) }
72
+ else
73
+ block = current_scope_restoring_block(&block)
74
+ scoping { _new(attributes, &block) }
75
+ end
72
76
  end
73
77
  alias build new
74
78
 
@@ -148,7 +152,7 @@ module ActiveRecord
148
152
  # above can be alternatively written this way:
149
153
  #
150
154
  # # Find the first user named "Scarlett" or create a new one with a
151
- # # different last name.
155
+ # # particular last name.
152
156
  # User.find_or_create_by(first_name: 'Scarlett') do |user|
153
157
  # user.last_name = 'Johansson'
154
158
  # end
@@ -158,38 +162,41 @@ module ActiveRecord
158
162
  # failed due to validation errors it won't be persisted, you get what
159
163
  # #create returns in such situation.
160
164
  #
161
- # Please note <b>this method is not atomic</b>, it runs first a SELECT, and if
162
- # there are no results an INSERT is attempted. If there are other threads
163
- # or processes there is a race condition between both calls and it could
164
- # be the case that you end up with two similar records.
165
+ # If creation failed because of a unique constraint, this method will
166
+ # assume it encountered a race condition and will try finding the record
167
+ # once more If somehow the second find still find no record because a
168
+ # concurrent DELETE happened, it will then raise an
169
+ # ActiveRecord::RecordNotFound exception.
165
170
  #
166
- # If this might be a problem for your application, please see #create_or_find_by.
171
+ # Please note <b>this method is not atomic</b>, it runs first a SELECT,
172
+ # and if there are no results an INSERT is attempted. So if the table
173
+ # doesn't have a relevant unique constraint it could be the case that
174
+ # you end up with two or more similar records.
167
175
  def find_or_create_by(attributes, &block)
168
- find_by(attributes) || create(attributes, &block)
176
+ find_by(attributes) || create_or_find_by(attributes, &block)
169
177
  end
170
178
 
171
179
  # Like #find_or_create_by, but calls
172
180
  # {create!}[rdoc-ref:Persistence::ClassMethods#create!] so an exception
173
181
  # is raised if the created record is invalid.
174
182
  def find_or_create_by!(attributes, &block)
175
- find_by(attributes) || create!(attributes, &block)
183
+ find_by(attributes) || create_or_find_by!(attributes, &block)
176
184
  end
177
185
 
178
- # Attempts to create a record with the given attributes in a table that has a unique constraint
186
+ # Attempts to create a record with the given attributes in a table that has a unique database constraint
179
187
  # on one or several of its columns. If a row already exists with one or several of these
180
188
  # unique constraints, the exception such an insertion would normally raise is caught,
181
189
  # and the existing record with those attributes is found using #find_by!.
182
190
  #
183
- # This is similar to #find_or_create_by, but avoids the problem of stale reads between the SELECT
184
- # and the INSERT, as that method needs to first query the table, then attempt to insert a row
185
- # if none is found.
191
+ # This is similar to #find_or_create_by, but tries to create the record first. As such it is
192
+ # better suited for cases where the record is most likely not to exist yet.
186
193
  #
187
194
  # There are several drawbacks to #create_or_find_by, though:
188
195
  #
189
- # * The underlying table must have the relevant columns defined with unique constraints.
196
+ # * The underlying table must have the relevant columns defined with unique database constraints.
190
197
  # * A unique constraint violation may be triggered by only one, or at least less than all,
191
198
  # of the given attributes. This means that the subsequent #find_by! may fail to find a
192
- # matching record, which will then raise an <tt>ActiveRecord::RecordNotFound</tt> exception,
199
+ # matching record, which will then raise an ActiveRecord::RecordNotFound exception,
193
200
  # rather than a record with the given attributes.
194
201
  # * While we avoid the race condition between SELECT -> INSERT from #find_or_create_by,
195
202
  # we actually have another race condition between INSERT -> SELECT, which can be triggered
@@ -198,7 +205,7 @@ module ActiveRecord
198
205
  # * It relies on exception handling to handle control flow, which may be marginally slower.
199
206
  # * The primary key may auto-increment on each create, even if it fails. This can accelerate
200
207
  # the problem of running out of integers, if the underlying table is still stuck on a primary
201
- # key of type int (note: All Rails apps since 5.1+ have defaulted to bigint, which is not liable
208
+ # key of type int (note: All \Rails apps since 5.1+ have defaulted to bigint, which is not liable
202
209
  # to this problem).
203
210
  #
204
211
  # This method will return a record if all given attributes are covered by unique constraints
@@ -208,7 +215,11 @@ module ActiveRecord
208
215
  def create_or_find_by(attributes, &block)
209
216
  transaction(requires_new: true) { create(attributes, &block) }
210
217
  rescue ActiveRecord::RecordNotUnique
211
- find_by!(attributes)
218
+ if connection.transaction_open?
219
+ where(attributes).lock.find_by!(attributes)
220
+ else
221
+ find_by!(attributes)
222
+ end
212
223
  end
213
224
 
214
225
  # Like #create_or_find_by, but calls
@@ -217,7 +228,11 @@ module ActiveRecord
217
228
  def create_or_find_by!(attributes, &block)
218
229
  transaction(requires_new: true) { create!(attributes, &block) }
219
230
  rescue ActiveRecord::RecordNotUnique
220
- find_by!(attributes)
231
+ if connection.transaction_open?
232
+ where(attributes).lock.find_by!(attributes)
233
+ else
234
+ find_by!(attributes)
235
+ end
221
236
  end
222
237
 
223
238
  # Like #find_or_create_by, but calls {new}[rdoc-ref:Core#new]
@@ -235,8 +250,8 @@ module ActiveRecord
235
250
  #
236
251
  # Please see further details in the
237
252
  # {Active Record Query Interface guide}[https://guides.rubyonrails.org/active_record_querying.html#running-explain].
238
- def explain
239
- exec_explain(collecting_queries_for_explain { exec_queries })
253
+ def explain(*options)
254
+ exec_explain(collecting_queries_for_explain { exec_queries }, options)
240
255
  end
241
256
 
242
257
  # Converts relation objects to Array.
@@ -257,37 +272,56 @@ module ActiveRecord
257
272
 
258
273
  # Returns size of the records.
259
274
  def size
260
- loaded? ? @records.length : count(:all)
275
+ if loaded?
276
+ records.length
277
+ else
278
+ count(:all)
279
+ end
261
280
  end
262
281
 
263
282
  # Returns true if there are no records.
264
283
  def empty?
265
- return @records.empty? if loaded?
266
- !exists?
284
+ return true if @none
285
+
286
+ if loaded?
287
+ records.empty?
288
+ else
289
+ !exists?
290
+ end
267
291
  end
268
292
 
269
293
  # Returns true if there are no records.
270
- def none?
271
- return super if block_given?
294
+ def none?(*args)
295
+ return true if @none
296
+
297
+ return super if args.present? || block_given?
272
298
  empty?
273
299
  end
274
300
 
275
301
  # Returns true if there are any records.
276
- def any?
277
- return super if block_given?
302
+ def any?(*args)
303
+ return false if @none
304
+
305
+ return super if args.present? || block_given?
278
306
  !empty?
279
307
  end
280
308
 
281
309
  # Returns true if there is exactly one record.
282
- def one?
283
- return super if block_given?
284
- limit_value ? records.one? : size == 1
310
+ def one?(*args)
311
+ return false if @none
312
+
313
+ return super if args.present? || block_given?
314
+ return records.one? if loaded?
315
+ limited_count == 1
285
316
  end
286
317
 
287
318
  # Returns true if there is more than one record.
288
319
  def many?
320
+ return false if @none
321
+
289
322
  return super if block_given?
290
- limit_value ? records.many? : size > 1
323
+ return records.many? if loaded?
324
+ limited_count > 1
291
325
  end
292
326
 
293
327
  # Returns a stable cache key that can be used to identify this query.
@@ -297,7 +331,7 @@ module ActiveRecord
297
331
  # # => "products/query-1850ab3d302391b85b8693e941286659"
298
332
  #
299
333
  # If ActiveRecord::Base.collection_cache_versioning is turned off, as it was
300
- # in Rails 6.0 and earlier, the cache key will also include a version.
334
+ # in \Rails 6.0 and earlier, the cache key will also include a version.
301
335
  #
302
336
  # ActiveRecord::Base.collection_cache_versioning = false
303
337
  # Product.where("name like ?", "%Cosmic Encounter%").cache_key
@@ -344,7 +378,7 @@ module ActiveRecord
344
378
  def compute_cache_version(timestamp_column) # :nodoc:
345
379
  timestamp_column = timestamp_column.to_s
346
380
 
347
- if loaded? || distinct_value
381
+ if loaded?
348
382
  size = records.size
349
383
  if size > 0
350
384
  timestamp = records.map { |record| record.read_attribute(timestamp_column) }.max
@@ -357,6 +391,7 @@ module ActiveRecord
357
391
 
358
392
  if collection.has_limit_or_offset?
359
393
  query = collection.select("#{column} AS collection_cache_key_timestamp")
394
+ query._select!(table[Arel.star]) if distinct_value && collection.select_values.empty?
360
395
  subquery_alias = "subquery_for_cache_key"
361
396
  subquery_column = "#{subquery_alias}.collection_cache_key_timestamp"
362
397
  arel = query.build_subquery(subquery_alias, select_values % subquery_column)
@@ -377,7 +412,7 @@ module ActiveRecord
377
412
  end
378
413
 
379
414
  if timestamp
380
- "#{size}-#{timestamp.utc.to_s(cache_timestamp_format)}"
415
+ "#{size}-#{timestamp.utc.to_fs(cache_timestamp_format)}"
381
416
  else
382
417
  "#{size}"
383
418
  end
@@ -398,17 +433,30 @@ module ActiveRecord
398
433
  # Comment.where(post_id: 1).scoping do
399
434
  # Comment.first
400
435
  # end
401
- # # => SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = 1 ORDER BY "comments"."id" ASC LIMIT 1
436
+ # # SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = 1 ORDER BY "comments"."id" ASC LIMIT 1
437
+ #
438
+ # If <tt>all_queries: true</tt> is passed, scoping will apply to all queries
439
+ # for the relation including +update+ and +delete+ on instances.
440
+ # Once +all_queries+ is set to true it cannot be set to false in a
441
+ # nested block.
402
442
  #
403
443
  # Please check unscoped if you want to remove all previous scopes (including
404
444
  # the default_scope) during the execution of a block.
405
- def scoping
406
- already_in_scope? ? yield : _scoping(self) { yield }
445
+ def scoping(all_queries: nil, &block)
446
+ registry = klass.scope_registry
447
+ if global_scope?(registry) && all_queries == false
448
+ raise ArgumentError, "Scoping is set to apply to all queries and cannot be unset in a nested block."
449
+ elsif already_in_scope?(registry)
450
+ yield
451
+ else
452
+ _scoping(self, registry, all_queries, &block)
453
+ end
407
454
  end
408
455
 
409
- def _exec_scope(*args, &block) # :nodoc:
456
+ def _exec_scope(...) # :nodoc:
410
457
  @delegate_to_klass = true
411
- _scoping(nil) { instance_exec(*args, &block) || self }
458
+ registry = klass.scope_registry
459
+ _scoping(nil, registry) { instance_exec(...) || self }
412
460
  ensure
413
461
  @delegate_to_klass = false
414
462
  end
@@ -422,7 +470,8 @@ module ActiveRecord
422
470
  #
423
471
  # ==== Parameters
424
472
  #
425
- # * +updates+ - A string, array, or hash representing the SET part of an SQL statement.
473
+ # * +updates+ - A string, array, or hash representing the SET part of an SQL statement. Any strings provided will
474
+ # be type cast, unless you use +Arel.sql+. (Don't pass user-provided values to +Arel.sql+.)
426
475
  #
427
476
  # ==== Examples
428
477
  #
@@ -437,19 +486,13 @@ module ActiveRecord
437
486
  #
438
487
  # # Update all invoices and set the number column to its id value.
439
488
  # Invoice.update_all('number = id')
489
+ #
490
+ # # Update all books with 'Rails' in their title
491
+ # Book.where('title LIKE ?', '%Rails%').update_all(title: Arel.sql("title + ' - volume 1'"))
440
492
  def update_all(updates)
441
493
  raise ArgumentError, "Empty list of attributes to change" if updates.blank?
442
494
 
443
- arel = eager_loading? ? apply_join_dependency.arel : build_arel
444
- arel.source.left = table
445
-
446
- stmt = Arel::UpdateManager.new
447
- stmt.table(arel.source)
448
- stmt.key = table[primary_key]
449
- stmt.take(arel.limit)
450
- stmt.offset(arel.offset)
451
- stmt.order(*arel.orders)
452
- stmt.wheres = arel.constraints
495
+ return 0 if @none
453
496
 
454
497
  if updates.is_a?(Hash)
455
498
  if klass.locking_enabled? &&
@@ -458,11 +501,17 @@ module ActiveRecord
458
501
  attr = table[klass.locking_column]
459
502
  updates[attr.name] = _increment_attribute(attr)
460
503
  end
461
- stmt.set _substitute_values(updates)
504
+ values = _substitute_values(updates)
462
505
  else
463
- stmt.set Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name))
506
+ values = Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name))
464
507
  end
465
508
 
509
+ arel = eager_loading? ? apply_join_dependency.arel : build_arel
510
+ arel.source.left = table
511
+
512
+ group_values_arel_columns = arel_columns(group_values.uniq)
513
+ having_clause_ast = having_clause.ast unless having_clause.empty?
514
+ stmt = arel.compile_update(values, table[primary_key], having_clause_ast, group_values_arel_columns)
466
515
  klass.connection.update(stmt, "#{klass} Update All").tap { reset }
467
516
  end
468
517
 
@@ -474,6 +523,14 @@ module ActiveRecord
474
523
  end
475
524
  end
476
525
 
526
+ def update!(id = :all, attributes) # :nodoc:
527
+ if id == :all
528
+ each { |record| record.update!(attributes) }
529
+ else
530
+ klass.update!(id, attributes)
531
+ end
532
+ end
533
+
477
534
  # Updates the counters of the records in the current relation.
478
535
  #
479
536
  # ==== Parameters
@@ -572,6 +629,8 @@ module ActiveRecord
572
629
  # Post.distinct.delete_all
573
630
  # # => ActiveRecord::ActiveRecordError: delete_all doesn't support distinct
574
631
  def delete_all
632
+ return 0 if @none
633
+
575
634
  invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
576
635
  value = @values[method]
577
636
  method == :distinct ? value : value&.any?
@@ -583,15 +642,11 @@ module ActiveRecord
583
642
  arel = eager_loading? ? apply_join_dependency.arel : build_arel
584
643
  arel.source.left = table
585
644
 
586
- stmt = Arel::DeleteManager.new
587
- stmt.from(arel.source)
588
- stmt.key = table[primary_key]
589
- stmt.take(arel.limit)
590
- stmt.offset(arel.offset)
591
- stmt.order(*arel.orders)
592
- stmt.wheres = arel.constraints
645
+ group_values_arel_columns = arel_columns(group_values.uniq)
646
+ having_clause_ast = having_clause.ast unless having_clause.empty?
647
+ stmt = arel.compile_delete(table[primary_key], having_clause_ast, group_values_arel_columns)
593
648
 
594
- klass.connection.delete(stmt, "#{klass} Destroy").tap { reset }
649
+ klass.connection.delete(stmt, "#{klass} Delete All").tap { reset }
595
650
  end
596
651
 
597
652
  # Finds and destroys all records matching the specified conditions.
@@ -620,6 +675,47 @@ module ActiveRecord
620
675
  where(*args).delete_all
621
676
  end
622
677
 
678
+ # Schedule the query to be performed from a background thread pool.
679
+ #
680
+ # Post.where(published: true).load_async # => #<ActiveRecord::Relation>
681
+ #
682
+ # When the +Relation+ is iterated, if the background query wasn't executed yet,
683
+ # it will be performed by the foreground thread.
684
+ #
685
+ # Note that {config.active_record.async_query_executor}[https://guides.rubyonrails.org/configuring.html#config-active-record-async-query-executor] must be configured
686
+ # for queries to actually be executed concurrently. Otherwise it defaults to
687
+ # executing them in the foreground.
688
+ #
689
+ # +load_async+ will also fall back to executing in the foreground in the test environment when transactional
690
+ # fixtures are enabled.
691
+ #
692
+ # If the query was actually executed in the background, the Active Record logs will show
693
+ # it by prefixing the log line with <tt>ASYNC</tt>:
694
+ #
695
+ # ASYNC Post Load (0.0ms) (db time 2ms) SELECT "posts".* FROM "posts" LIMIT 100
696
+ def load_async
697
+ return load if !connection.async_enabled?
698
+
699
+ unless loaded?
700
+ result = exec_main_query(async: connection.current_transaction.closed?)
701
+
702
+ if result.is_a?(Array)
703
+ @records = result
704
+ else
705
+ @future_result = result
706
+ end
707
+ @loaded = true
708
+ end
709
+
710
+ self
711
+ end
712
+
713
+ # Returns <tt>true</tt> if the relation was scheduled on the background
714
+ # thread pool.
715
+ def scheduled?
716
+ !!@future_result
717
+ end
718
+
623
719
  # Causes the records to be loaded from the database if they have not
624
720
  # been loaded already. You can use this if for some reason you need
625
721
  # to explicitly load some records before actually using them. The
@@ -627,7 +723,7 @@ module ActiveRecord
627
723
  #
628
724
  # Post.where(published: true).load # => #<ActiveRecord::Relation>
629
725
  def load(&block)
630
- unless loaded?
726
+ if !loaded? || scheduled?
631
727
  @records = exec_queries(&block)
632
728
  @loaded = true
633
729
  end
@@ -642,29 +738,30 @@ module ActiveRecord
642
738
  end
643
739
 
644
740
  def reset
741
+ @future_result&.cancel
742
+ @future_result = nil
645
743
  @delegate_to_klass = false
646
744
  @to_sql = @arel = @loaded = @should_eager_load = nil
647
745
  @offsets = @take = nil
648
746
  @cache_keys = nil
649
- @records = [].freeze
747
+ @cache_versions = nil
748
+ @records = nil
650
749
  self
651
750
  end
652
751
 
653
752
  # Returns sql statement for the relation.
654
753
  #
655
754
  # User.where(name: 'Oscar').to_sql
656
- # # => SELECT "users".* FROM "users" WHERE "users"."name" = 'Oscar'
755
+ # # SELECT "users".* FROM "users" WHERE "users"."name" = 'Oscar'
657
756
  def to_sql
658
- @to_sql ||= begin
659
- if eager_loading?
660
- apply_join_dependency do |relation, join_dependency|
661
- relation = join_dependency.apply_column_aliases(relation)
662
- relation.to_sql
663
- end
664
- else
665
- conn = klass.connection
666
- conn.unprepared_statement { conn.to_sql(arel) }
757
+ @to_sql ||= if eager_loading?
758
+ apply_join_dependency do |relation, join_dependency|
759
+ relation = join_dependency.apply_column_aliases(relation)
760
+ relation.to_sql
667
761
  end
762
+ else
763
+ conn = klass.connection
764
+ conn.unprepared_statement { conn.to_sql(arel) }
668
765
  end
669
766
  end
670
767
 
@@ -672,7 +769,7 @@ module ActiveRecord
672
769
  #
673
770
  # User.where(name: 'Oscar').where_values_hash
674
771
  # # => {name: "Oscar"}
675
- def where_values_hash(relation_table_name = klass.table_name)
772
+ def where_values_hash(relation_table_name = klass.table_name) # :nodoc:
676
773
  where_clause.to_h(relation_table_name)
677
774
  end
678
775
 
@@ -692,7 +789,7 @@ module ActiveRecord
692
789
  # Joins that are also marked for preloading. In which case we should just eager load them.
693
790
  # Note that this is a naive implementation because we could have strings and symbols which
694
791
  # represent the same association, but that aren't matched by this. Also, we could have
695
- # nested hashes which partially match, e.g. { a: :b } & { a: [:b, :c] }
792
+ # nested hashes which partially match, e.g. <tt>{ a: :b } & { a: [:b, :c] }</tt>
696
793
  def joined_includes_values
697
794
  includes_values & joins_values
698
795
  end
@@ -709,8 +806,13 @@ module ActiveRecord
709
806
  end
710
807
  end
711
808
 
712
- def pretty_print(q)
713
- q.pp(records)
809
+ def pretty_print(pp)
810
+ subject = loaded? ? records : annotate("loading for pp")
811
+ entries = subject.take([limit_value, 11].compact.min)
812
+
813
+ entries[10] = "..." if entries.size == 11
814
+
815
+ pp.pp(entries)
714
816
  end
715
817
 
716
818
  # Returns true if relation is blank.
@@ -722,6 +824,10 @@ module ActiveRecord
722
824
  @values.dup
723
825
  end
724
826
 
827
+ def values_for_queries # :nodoc:
828
+ @values.except(:extending, :skip_query_cache, :strict_loading)
829
+ end
830
+
725
831
  def inspect
726
832
  subject = loaded? ? records : annotate("loading for inspect")
727
833
  entries = subject.take([limit_value, 11].compact.min).map!(&:inspect)
@@ -756,11 +862,9 @@ module ActiveRecord
756
862
  def preload_associations(records) # :nodoc:
757
863
  preload = preload_values
758
864
  preload += includes_values unless eager_loading?
759
- preloader = nil
760
865
  scope = strict_loading_value ? StrictLoadingScope : nil
761
866
  preload.each do |associations|
762
- preloader ||= build_preloader
763
- preloader.preload records, associations, scope
867
+ ActiveRecord::Associations::Preloader.new(records: records, associations: associations, scope: scope).call
764
868
  end
765
869
  end
766
870
 
@@ -770,13 +874,13 @@ module ActiveRecord
770
874
  @loaded = true
771
875
  end
772
876
 
773
- def null_relation? # :nodoc:
774
- is_a?(NullRelation)
877
+ private
878
+ def already_in_scope?(registry)
879
+ @delegate_to_klass && registry.current_scope(klass, true)
775
880
  end
776
881
 
777
- private
778
- def already_in_scope?
779
- @delegate_to_klass && klass.current_scope(true)
882
+ def global_scope?(registry)
883
+ registry.global_current_scope(klass, true)
780
884
  end
781
885
 
782
886
  def current_scope_restoring_block(&block)
@@ -799,11 +903,20 @@ module ActiveRecord
799
903
  klass.create!(attributes, &block)
800
904
  end
801
905
 
802
- def _scoping(scope)
803
- previous, klass.current_scope = klass.current_scope(true), scope
906
+ def _scoping(scope, registry, all_queries = false)
907
+ previous = registry.current_scope(klass, true)
908
+ registry.set_current_scope(klass, scope)
909
+
910
+ if all_queries
911
+ previous_global = registry.global_current_scope(klass, true)
912
+ registry.set_global_current_scope(klass, scope)
913
+ end
804
914
  yield
805
915
  ensure
806
- klass.current_scope = previous
916
+ registry.set_current_scope(klass, previous)
917
+ if all_queries
918
+ registry.set_global_current_scope(klass, previous_global)
919
+ end
807
920
  end
808
921
 
809
922
  def _substitute_values(values)
@@ -826,44 +939,69 @@ module ActiveRecord
826
939
 
827
940
  def exec_queries(&block)
828
941
  skip_query_cache_if_necessary do
829
- records =
830
- if where_clause.contradiction?
831
- []
832
- elsif eager_loading?
833
- apply_join_dependency do |relation, join_dependency|
834
- if relation.null_relation?
835
- []
836
- else
837
- relation = join_dependency.apply_column_aliases(relation)
838
- rows = connection.select_all(relation.arel, "SQL")
839
- join_dependency.instantiate(rows, strict_loading_value, &block)
840
- end.freeze
841
- end
842
- else
843
- klass.find_by_sql(arel, &block).freeze
844
- end
942
+ rows = if scheduled?
943
+ future = @future_result
944
+ @future_result = nil
945
+ future.result
946
+ else
947
+ exec_main_query
948
+ end
845
949
 
950
+ records = instantiate_records(rows, &block)
846
951
  preload_associations(records) unless skip_preloading_value
847
952
 
848
953
  records.each(&:readonly!) if readonly_value
849
- records.each(&:strict_loading!) if strict_loading_value
954
+ records.each { |record| record.strict_loading!(strict_loading_value) } unless strict_loading_value.nil?
850
955
 
851
956
  records
852
957
  end
853
958
  end
854
959
 
855
- def skip_query_cache_if_necessary
856
- if skip_query_cache_value
857
- uncached do
858
- yield
960
+ def exec_main_query(async: false)
961
+ if @none
962
+ if async
963
+ return Promise::Complete.new([])
964
+ else
965
+ return []
966
+ end
967
+ end
968
+
969
+ skip_query_cache_if_necessary do
970
+ if where_clause.contradiction?
971
+ [].freeze
972
+ elsif eager_loading?
973
+ apply_join_dependency do |relation, join_dependency|
974
+ if relation.null_relation?
975
+ [].freeze
976
+ else
977
+ relation = join_dependency.apply_column_aliases(relation)
978
+ @_join_dependency = join_dependency
979
+ connection.select_all(relation.arel, "SQL", async: async)
980
+ end
981
+ end
982
+ else
983
+ klass._query_by_sql(arel, async: async)
859
984
  end
985
+ end
986
+ end
987
+
988
+ def instantiate_records(rows, &block)
989
+ return [].freeze if rows.empty?
990
+ if eager_loading?
991
+ records = @_join_dependency.instantiate(rows, strict_loading_value, &block).freeze
992
+ @_join_dependency = nil
993
+ records
860
994
  else
861
- yield
995
+ klass._load_from_sql(rows, &block).freeze
862
996
  end
863
997
  end
864
998
 
865
- def build_preloader
866
- ActiveRecord::Associations::Preloader.new
999
+ def skip_query_cache_if_necessary(&block)
1000
+ if skip_query_cache_value
1001
+ uncached(&block)
1002
+ else
1003
+ yield
1004
+ end
867
1005
  end
868
1006
 
869
1007
  def references_eager_loaded_tables?
@@ -889,5 +1027,9 @@ module ActiveRecord
889
1027
  # ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
890
1028
  string.scan(/[a-zA-Z_][.\w]+(?=.?\.)/).map!(&:downcase) - ["raw_sql_"]
891
1029
  end
1030
+
1031
+ def limited_count
1032
+ limit_value ? count : limit(2).count
1033
+ end
892
1034
  end
893
1035
  end