activerecord 6.1.7 → 7.1.5

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 (311) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2030 -1020
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +18 -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 +51 -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 +39 -35
  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/join_association.rb +3 -2
  27. data/lib/active_record/associations/join_dependency.rb +28 -20
  28. data/lib/active_record/associations/preloader/association.rb +210 -52
  29. data/lib/active_record/associations/preloader/batch.rb +48 -0
  30. data/lib/active_record/associations/preloader/branch.rb +147 -0
  31. data/lib/active_record/associations/preloader/through_association.rb +50 -14
  32. data/lib/active_record/associations/preloader.rb +50 -121
  33. data/lib/active_record/associations/singular_association.rb +9 -3
  34. data/lib/active_record/associations/through_association.rb +25 -14
  35. data/lib/active_record/associations.rb +446 -306
  36. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  37. data/lib/active_record/attribute_assignment.rb +1 -3
  38. data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
  39. data/lib/active_record/attribute_methods/dirty.rb +73 -22
  40. data/lib/active_record/attribute_methods/primary_key.rb +78 -26
  41. data/lib/active_record/attribute_methods/query.rb +31 -19
  42. data/lib/active_record/attribute_methods/read.rb +27 -12
  43. data/lib/active_record/attribute_methods/serialization.rb +194 -37
  44. data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
  45. data/lib/active_record/attribute_methods/write.rb +12 -15
  46. data/lib/active_record/attribute_methods.rb +161 -40
  47. data/lib/active_record/attributes.rb +27 -38
  48. data/lib/active_record/autosave_association.rb +65 -31
  49. data/lib/active_record/base.rb +25 -2
  50. data/lib/active_record/callbacks.rb +18 -34
  51. data/lib/active_record/coders/column_serializer.rb +61 -0
  52. data/lib/active_record/coders/json.rb +1 -1
  53. data/lib/active_record/coders/yaml_column.rb +70 -46
  54. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
  55. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +113 -597
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -27
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +367 -141
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
  70. data/lib/active_record/connection_adapters/column.rb +13 -0
  71. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +39 -14
  78. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
  80. data/lib/active_record/connection_adapters/pool_config.rb +20 -11
  81. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  89. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
  91. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  94. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
  96. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
  97. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
  98. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
  99. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
  100. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +397 -75
  101. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  102. data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
  103. data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
  104. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  105. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
  106. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
  107. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
  108. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
  109. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +296 -104
  110. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  111. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  112. data/lib/active_record/connection_adapters/trilogy_adapter.rb +258 -0
  113. data/lib/active_record/connection_adapters.rb +9 -6
  114. data/lib/active_record/connection_handling.rb +108 -137
  115. data/lib/active_record/core.rb +242 -233
  116. data/lib/active_record/counter_cache.rb +52 -27
  117. data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
  118. data/lib/active_record/database_configurations/database_config.rb +21 -12
  119. data/lib/active_record/database_configurations/hash_config.rb +88 -16
  120. data/lib/active_record/database_configurations/url_config.rb +18 -12
  121. data/lib/active_record/database_configurations.rb +95 -59
  122. data/lib/active_record/delegated_type.rb +66 -20
  123. data/lib/active_record/deprecator.rb +7 -0
  124. data/lib/active_record/destroy_association_async_job.rb +4 -2
  125. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  126. data/lib/active_record/dynamic_matchers.rb +1 -1
  127. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  128. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  129. data/lib/active_record/encryption/cipher.rb +53 -0
  130. data/lib/active_record/encryption/config.rb +68 -0
  131. data/lib/active_record/encryption/configurable.rb +60 -0
  132. data/lib/active_record/encryption/context.rb +42 -0
  133. data/lib/active_record/encryption/contexts.rb +76 -0
  134. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  135. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  136. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  137. data/lib/active_record/encryption/encrypted_attribute_type.rb +155 -0
  138. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  139. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  140. data/lib/active_record/encryption/encryptor.rb +155 -0
  141. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  142. data/lib/active_record/encryption/errors.rb +15 -0
  143. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  144. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  145. data/lib/active_record/encryption/key.rb +28 -0
  146. data/lib/active_record/encryption/key_generator.rb +53 -0
  147. data/lib/active_record/encryption/key_provider.rb +46 -0
  148. data/lib/active_record/encryption/message.rb +33 -0
  149. data/lib/active_record/encryption/message_serializer.rb +92 -0
  150. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  151. data/lib/active_record/encryption/properties.rb +76 -0
  152. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  153. data/lib/active_record/encryption/scheme.rb +100 -0
  154. data/lib/active_record/encryption.rb +58 -0
  155. data/lib/active_record/enum.rb +154 -63
  156. data/lib/active_record/errors.rb +172 -15
  157. data/lib/active_record/explain.rb +23 -3
  158. data/lib/active_record/explain_registry.rb +11 -6
  159. data/lib/active_record/explain_subscriber.rb +1 -1
  160. data/lib/active_record/fixture_set/file.rb +15 -1
  161. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  162. data/lib/active_record/fixture_set/render_context.rb +2 -0
  163. data/lib/active_record/fixture_set/table_row.rb +70 -14
  164. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  165. data/lib/active_record/fixtures.rb +147 -86
  166. data/lib/active_record/future_result.rb +174 -0
  167. data/lib/active_record/gem_version.rb +3 -3
  168. data/lib/active_record/inheritance.rb +81 -29
  169. data/lib/active_record/insert_all.rb +135 -22
  170. data/lib/active_record/integration.rb +11 -10
  171. data/lib/active_record/internal_metadata.rb +119 -33
  172. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  173. data/lib/active_record/locking/optimistic.rb +37 -22
  174. data/lib/active_record/locking/pessimistic.rb +15 -6
  175. data/lib/active_record/log_subscriber.rb +52 -19
  176. data/lib/active_record/marshalling.rb +59 -0
  177. data/lib/active_record/message_pack.rb +124 -0
  178. data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
  179. data/lib/active_record/middleware/database_selector.rb +23 -13
  180. data/lib/active_record/middleware/shard_selector.rb +62 -0
  181. data/lib/active_record/migration/command_recorder.rb +112 -14
  182. data/lib/active_record/migration/compatibility.rb +233 -46
  183. data/lib/active_record/migration/default_strategy.rb +23 -0
  184. data/lib/active_record/migration/execution_strategy.rb +19 -0
  185. data/lib/active_record/migration/join_table.rb +1 -1
  186. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  187. data/lib/active_record/migration.rb +361 -173
  188. data/lib/active_record/model_schema.rb +125 -101
  189. data/lib/active_record/nested_attributes.rb +50 -20
  190. data/lib/active_record/no_touching.rb +3 -3
  191. data/lib/active_record/normalization.rb +167 -0
  192. data/lib/active_record/persistence.rb +409 -88
  193. data/lib/active_record/promise.rb +84 -0
  194. data/lib/active_record/query_cache.rb +4 -22
  195. data/lib/active_record/query_logs.rb +174 -0
  196. data/lib/active_record/query_logs_formatter.rb +41 -0
  197. data/lib/active_record/querying.rb +29 -6
  198. data/lib/active_record/railtie.rb +220 -44
  199. data/lib/active_record/railties/controller_runtime.rb +15 -10
  200. data/lib/active_record/railties/databases.rake +188 -252
  201. data/lib/active_record/railties/job_runtime.rb +23 -0
  202. data/lib/active_record/readonly_attributes.rb +41 -3
  203. data/lib/active_record/reflection.rb +248 -81
  204. data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
  205. data/lib/active_record/relation/batches.rb +192 -63
  206. data/lib/active_record/relation/calculations.rb +246 -90
  207. data/lib/active_record/relation/delegation.rb +28 -14
  208. data/lib/active_record/relation/finder_methods.rb +108 -51
  209. data/lib/active_record/relation/merger.rb +22 -13
  210. data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
  211. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  212. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  213. data/lib/active_record/relation/predicate_builder.rb +27 -20
  214. data/lib/active_record/relation/query_attribute.rb +30 -12
  215. data/lib/active_record/relation/query_methods.rb +670 -129
  216. data/lib/active_record/relation/record_fetch_warning.rb +7 -9
  217. data/lib/active_record/relation/spawn_methods.rb +20 -3
  218. data/lib/active_record/relation/where_clause.rb +10 -19
  219. data/lib/active_record/relation.rb +287 -120
  220. data/lib/active_record/result.rb +37 -11
  221. data/lib/active_record/runtime_registry.rb +32 -13
  222. data/lib/active_record/sanitization.rb +65 -20
  223. data/lib/active_record/schema.rb +36 -22
  224. data/lib/active_record/schema_dumper.rb +73 -24
  225. data/lib/active_record/schema_migration.rb +68 -33
  226. data/lib/active_record/scoping/default.rb +72 -15
  227. data/lib/active_record/scoping/named.rb +5 -13
  228. data/lib/active_record/scoping.rb +65 -34
  229. data/lib/active_record/secure_password.rb +60 -0
  230. data/lib/active_record/secure_token.rb +21 -3
  231. data/lib/active_record/serialization.rb +6 -1
  232. data/lib/active_record/signed_id.rb +10 -8
  233. data/lib/active_record/store.rb +10 -10
  234. data/lib/active_record/suppressor.rb +13 -15
  235. data/lib/active_record/table_metadata.rb +16 -3
  236. data/lib/active_record/tasks/database_tasks.rb +251 -140
  237. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
  238. data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
  239. data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
  240. data/lib/active_record/test_databases.rb +1 -1
  241. data/lib/active_record/test_fixtures.rb +117 -96
  242. data/lib/active_record/timestamp.rb +32 -19
  243. data/lib/active_record/token_for.rb +113 -0
  244. data/lib/active_record/touch_later.rb +11 -6
  245. data/lib/active_record/transactions.rb +48 -27
  246. data/lib/active_record/translation.rb +3 -3
  247. data/lib/active_record/type/adapter_specific_registry.rb +32 -14
  248. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  249. data/lib/active_record/type/internal/timezone.rb +7 -2
  250. data/lib/active_record/type/serialized.rb +9 -5
  251. data/lib/active_record/type/time.rb +4 -0
  252. data/lib/active_record/type/type_map.rb +17 -20
  253. data/lib/active_record/type.rb +1 -2
  254. data/lib/active_record/validations/absence.rb +1 -1
  255. data/lib/active_record/validations/associated.rb +4 -4
  256. data/lib/active_record/validations/numericality.rb +5 -4
  257. data/lib/active_record/validations/presence.rb +5 -28
  258. data/lib/active_record/validations/uniqueness.rb +51 -6
  259. data/lib/active_record/validations.rb +8 -4
  260. data/lib/active_record/version.rb +1 -1
  261. data/lib/active_record.rb +335 -32
  262. data/lib/arel/attributes/attribute.rb +0 -8
  263. data/lib/arel/crud.rb +28 -22
  264. data/lib/arel/delete_manager.rb +18 -4
  265. data/lib/arel/errors.rb +10 -0
  266. data/lib/arel/factory_methods.rb +4 -0
  267. data/lib/arel/filter_predications.rb +9 -0
  268. data/lib/arel/insert_manager.rb +2 -3
  269. data/lib/arel/nodes/and.rb +4 -0
  270. data/lib/arel/nodes/binary.rb +6 -1
  271. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  272. data/lib/arel/nodes/casted.rb +1 -1
  273. data/lib/arel/nodes/cte.rb +36 -0
  274. data/lib/arel/nodes/delete_statement.rb +12 -13
  275. data/lib/arel/nodes/filter.rb +10 -0
  276. data/lib/arel/nodes/fragments.rb +35 -0
  277. data/lib/arel/nodes/function.rb +1 -0
  278. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  279. data/lib/arel/nodes/insert_statement.rb +2 -2
  280. data/lib/arel/nodes/leading_join.rb +8 -0
  281. data/lib/arel/nodes/node.rb +111 -2
  282. data/lib/arel/nodes/select_core.rb +2 -2
  283. data/lib/arel/nodes/select_statement.rb +2 -2
  284. data/lib/arel/nodes/sql_literal.rb +6 -0
  285. data/lib/arel/nodes/table_alias.rb +4 -0
  286. data/lib/arel/nodes/update_statement.rb +8 -3
  287. data/lib/arel/nodes.rb +5 -0
  288. data/lib/arel/predications.rb +13 -3
  289. data/lib/arel/select_manager.rb +10 -4
  290. data/lib/arel/table.rb +9 -6
  291. data/lib/arel/tree_manager.rb +5 -13
  292. data/lib/arel/update_manager.rb +18 -4
  293. data/lib/arel/visitors/dot.rb +80 -90
  294. data/lib/arel/visitors/mysql.rb +16 -3
  295. data/lib/arel/visitors/postgresql.rb +0 -10
  296. data/lib/arel/visitors/to_sql.rb +141 -20
  297. data/lib/arel/visitors/visitor.rb +2 -2
  298. data/lib/arel.rb +18 -3
  299. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  300. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  301. data/lib/rails/generators/active_record/migration.rb +3 -1
  302. data/lib/rails/generators/active_record/model/USAGE +113 -0
  303. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  304. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  305. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  306. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  307. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  308. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  309. metadata +96 -16
  310. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  311. data/lib/active_record/null_relation.rb +0 -67
@@ -6,20 +6,23 @@ require "zlib"
6
6
  require "set"
7
7
  require "active_support/dependencies"
8
8
  require "active_support/core_ext/digest/uuid"
9
- require "active_record/fixture_set/file"
10
- require "active_record/fixture_set/render_context"
11
- require "active_record/fixture_set/table_rows"
12
9
  require "active_record/test_fixtures"
13
10
 
14
11
  module ActiveRecord
15
- class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
12
+ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
16
13
  end
17
14
 
15
+ # = Active Record \Fixtures
16
+ #
18
17
  # \Fixtures are a way of organizing data that you want to test against; in short, sample data.
19
18
  #
20
- # They are stored in YAML files, one file per model, which are placed in the directory
21
- # appointed by <tt>ActiveSupport::TestCase.fixture_path=(path)</tt> (this is automatically
22
- # configured for Rails, so you can just put your files in <tt><your-rails-app>/test/fixtures/</tt>).
19
+ # They are stored in YAML files, one file per model, which are by default placed in either
20
+ # <tt><your-rails-app>/test/fixtures/</tt> or in the <tt>test/fixtures</tt>
21
+ # folder under any of your application's engines.
22
+ #
23
+ # The location can also be changed with ActiveSupport::TestCase.fixture_paths=,
24
+ # once you have <tt>require "rails/test_help"</tt> in your +test_helper.rb+.
25
+ #
23
26
  # The fixture file ends with the +.yml+ file extension, for example:
24
27
  # <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
25
28
  #
@@ -35,14 +38,21 @@ module ActiveRecord
35
38
  # name: Google
36
39
  # url: http://www.google.com
37
40
  #
38
- # This fixture file includes two fixtures. Each YAML fixture (ie. record) is given a name and
41
+ # This fixture file includes two fixtures. Each YAML fixture (i.e. record) is given a name and
39
42
  # is followed by an indented list of key/value pairs in the "key: value" format. Records are
40
43
  # separated by a blank line for your viewing pleasure.
41
44
  #
42
- # Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
43
- # See https://yaml.org/type/omap.html
44
- # for the specification. You will need ordered fixtures when you have foreign key constraints
45
- # on keys in the same table. This is commonly needed for tree structures. Example:
45
+ # == Ordering
46
+ #
47
+ # Fixtures by default are unordered. This is because the maps in YAML are unordered.
48
+ #
49
+ # If you want ordered fixtures, use the omap YAML type.
50
+ # See https://yaml.org/type/omap.html for the specification.
51
+ #
52
+ # You will need ordered fixtures when you have foreign key constraints
53
+ # on keys in the same table. This is commonly needed for tree structures.
54
+ #
55
+ # For example:
46
56
  #
47
57
  # --- !omap
48
58
  # - parent:
@@ -54,7 +64,7 @@ module ActiveRecord
54
64
  # parent_id: 1
55
65
  # title: Child
56
66
  #
57
- # = Using Fixtures in Test Cases
67
+ # == Using Fixtures in Test Cases
58
68
  #
59
69
  # Since fixtures are a testing construct, we use them in our unit and functional tests. There
60
70
  # are two ways to use the fixtures, but first let's take a look at a sample unit test:
@@ -124,7 +134,7 @@ module ActiveRecord
124
134
  # traversed in the database to create the fixture hash and/or instance variables. This is expensive for
125
135
  # large sets of fixtured data.
126
136
  #
127
- # = Dynamic fixtures with ERB
137
+ # == Dynamic fixtures with \ERB
128
138
  #
129
139
  # Sometimes you don't care about the content of the fixtures as much as you care about the volume.
130
140
  # In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load
@@ -152,7 +162,7 @@ module ActiveRecord
152
162
  # - define a helper method in <tt>test_helper.rb</tt>
153
163
  # module FixtureFileHelpers
154
164
  # def file_sha(path)
155
- # Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
165
+ # OpenSSL::Digest::SHA256.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
156
166
  # end
157
167
  # end
158
168
  # ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
@@ -162,7 +172,7 @@ module ActiveRecord
162
172
  # name: kitten.png
163
173
  # sha: <%= file_sha 'files/kitten.png' %>
164
174
  #
165
- # = Transactional Tests
175
+ # == Transactional Tests
166
176
  #
167
177
  # Test cases can use begin+rollback to isolate their changes to the database instead of having to
168
178
  # delete+insert for every test case.
@@ -198,7 +208,7 @@ module ActiveRecord
198
208
  # 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM.
199
209
  # Use InnoDB, MaxDB, or NDB instead.
200
210
  #
201
- # = Advanced Fixtures
211
+ # == Advanced Fixtures
202
212
  #
203
213
  # Fixtures that don't specify an ID get some extra features:
204
214
  #
@@ -212,7 +222,7 @@ module ActiveRecord
212
222
  # * Fixture label interpolation
213
223
  # * Support for YAML defaults
214
224
  #
215
- # == Stable, Autogenerated IDs
225
+ # === Stable, Autogenerated IDs
216
226
  #
217
227
  # Here, have a monkey fixture:
218
228
  #
@@ -241,13 +251,13 @@ module ActiveRecord
241
251
  # The generated ID for a given label is constant, so we can discover
242
252
  # any fixture's ID without loading anything, as long as we know the label.
243
253
  #
244
- # == Label references for associations (belongs_to, has_one, has_many)
254
+ # === Label references for associations (+belongs_to+, +has_one+, +has_many+)
245
255
  #
246
256
  # Specifying foreign keys in fixtures can be very fragile, not to
247
257
  # mention difficult to read. Since Active Record can figure out the ID of
248
258
  # any fixture from its label, you can specify FK's by label instead of ID.
249
259
  #
250
- # === belongs_to
260
+ # ==== +belongs_to+
251
261
  #
252
262
  # Let's break out some more monkeys and pirates.
253
263
  #
@@ -258,6 +268,8 @@ module ActiveRecord
258
268
  # name: Reginald the Pirate
259
269
  # monkey_id: 1
260
270
  #
271
+ # <code></code>
272
+ #
261
273
  # ### in monkeys.yml
262
274
  #
263
275
  # george:
@@ -275,6 +287,8 @@ module ActiveRecord
275
287
  # name: Reginald the Pirate
276
288
  # monkey: george
277
289
  #
290
+ # <code></code>
291
+ #
278
292
  # ### in monkeys.yml
279
293
  #
280
294
  # george:
@@ -286,7 +300,7 @@ module ActiveRecord
286
300
  # a target *label* for the *association* (monkey: george) rather than
287
301
  # a target *id* for the *FK* (<tt>monkey_id: 1</tt>).
288
302
  #
289
- # ==== Polymorphic belongs_to
303
+ # ==== Polymorphic +belongs_to+
290
304
  #
291
305
  # Supporting polymorphic relationships is a little bit more complicated, since
292
306
  # Active Record needs to know what type your association is pointing at. Something
@@ -296,6 +310,8 @@ module ActiveRecord
296
310
  #
297
311
  # belongs_to :eater, polymorphic: true
298
312
  #
313
+ # <code></code>
314
+ #
299
315
  # ### in fruits.yml
300
316
  #
301
317
  # apple:
@@ -311,9 +327,9 @@ module ActiveRecord
311
327
  #
312
328
  # Just provide the polymorphic target type and Active Record will take care of the rest.
313
329
  #
314
- # === has_and_belongs_to_many
330
+ # ==== +has_and_belongs_to_many+ or <tt>has_many :through</tt>
315
331
  #
316
- # Time to give our monkey some fruit.
332
+ # \Time to give our monkey some fruit.
317
333
  #
318
334
  # ### in monkeys.yml
319
335
  #
@@ -321,6 +337,8 @@ module ActiveRecord
321
337
  # id: 1
322
338
  # name: George the Monkey
323
339
  #
340
+ # <code></code>
341
+ #
324
342
  # ### in fruits.yml
325
343
  #
326
344
  # apple:
@@ -335,6 +353,8 @@ module ActiveRecord
335
353
  # id: 3
336
354
  # name: grape
337
355
  #
356
+ # <code></code>
357
+ #
338
358
  # ### in fruits_monkeys.yml
339
359
  #
340
360
  # apple_george:
@@ -358,6 +378,8 @@ module ActiveRecord
358
378
  # name: George the Monkey
359
379
  # fruits: apple, orange, grape
360
380
  #
381
+ # <code></code>
382
+ #
361
383
  # ### in fruits.yml
362
384
  #
363
385
  # apple:
@@ -375,7 +397,7 @@ module ActiveRecord
375
397
  # the fixture's model class and discovers the +has_and_belongs_to_many+
376
398
  # associations.
377
399
  #
378
- # == Autofilled Timestamp Columns
400
+ # === Autofilled \Timestamp Columns
379
401
  #
380
402
  # If your table/model specifies any of Active Record's
381
403
  # standard timestamp columns (+created_at+, +created_on+, +updated_at+, +updated_on+),
@@ -383,7 +405,7 @@ module ActiveRecord
383
405
  #
384
406
  # If you've set specific values, they'll be left alone.
385
407
  #
386
- # == Fixture label interpolation
408
+ # === Fixture label interpolation
387
409
  #
388
410
  # The label of the current fixture is always available as a column value:
389
411
  #
@@ -400,14 +422,18 @@ module ActiveRecord
400
422
  # monkey_id: <%= ActiveRecord::FixtureSet.identify(:reginald) %>
401
423
  # pirate_id: <%= ActiveRecord::FixtureSet.identify(:george) %>
402
424
  #
403
- # == Support for YAML defaults
425
+ # If the model uses UUID values for identifiers, add the +:uuid+ argument:
426
+ #
427
+ # ActiveRecord::FixtureSet.identify(:boaty_mcboatface, :uuid)
428
+ #
429
+ # === Support for YAML defaults
404
430
  #
405
431
  # You can set and reuse defaults in your fixtures YAML file.
406
432
  # This is the same technique used in the +database.yml+ file to specify
407
433
  # defaults:
408
434
  #
409
435
  # DEFAULTS: &DEFAULTS
410
- # created_on: <%= 3.weeks.ago.to_s(:db) %>
436
+ # created_on: <%= 3.weeks.ago.to_fs(:db) %>
411
437
  #
412
438
  # first:
413
439
  # name: Smurf
@@ -426,7 +452,7 @@ module ActiveRecord
426
452
  # _fixture:
427
453
  # ignore:
428
454
  # - base
429
- # # or use "ignore: base" when there is only one fixture needs to be ignored.
455
+ # # or use "ignore: base" when there is only one fixture that needs to be ignored.
430
456
  #
431
457
  # base: &base
432
458
  # admin: false
@@ -442,6 +468,45 @@ module ActiveRecord
442
468
  # In the above example, 'base' will be ignored when creating fixtures.
443
469
  # This can be used for common attributes inheriting.
444
470
  #
471
+ # == Composite Primary Key Fixtures
472
+ #
473
+ # Fixtures for composite primary key tables are fairly similar to normal tables.
474
+ # When using an id column, the column may be omitted as usual:
475
+ #
476
+ # # app/models/book.rb
477
+ # class Book < ApplicationRecord
478
+ # self.primary_key = [:author_id, :id]
479
+ # belongs_to :author
480
+ # end
481
+ #
482
+ # <code></code>
483
+ #
484
+ # # books.yml
485
+ # alices_adventure_in_wonderland:
486
+ # author_id: <%= ActiveRecord::FixtureSet.identify(:lewis_carroll) %>
487
+ # title: "Alice's Adventures in Wonderland"
488
+ #
489
+ # However, in order to support composite primary key relationships,
490
+ # you must use the `composite_identify` method:
491
+ #
492
+ # # app/models/book_orders.rb
493
+ # class BookOrder < ApplicationRecord
494
+ # self.primary_key = [:shop_id, :id]
495
+ # belongs_to :order, query_constraints: [:shop_id, :order_id]
496
+ # belongs_to :book, query_constraints: [:author_id, :book_id]
497
+ # end
498
+ #
499
+ # <code></code>
500
+ #
501
+ # # book_orders.yml
502
+ # alices_adventure_in_wonderland_in_books:
503
+ # author: lewis_carroll
504
+ # book_id: <%= ActiveRecord::FixtureSet.composite_identify(
505
+ # :alices_adventure_in_wonderland, Book.primary_key)[:id] %>
506
+ # shop: book_store
507
+ # order_id: <%= ActiveRecord::FixtureSet.composite_identify(
508
+ # :books, Order.primary_key)[:id] %>
509
+ #
445
510
  # == Configure the fixture model class
446
511
  #
447
512
  # It's possible to set the fixture's model class directly in the YAML file.
@@ -456,6 +521,10 @@ module ActiveRecord
456
521
  #
457
522
  # Any fixtures labeled "_fixture" are safely ignored.
458
523
  class FixtureSet
524
+ require "active_record/fixture_set/file"
525
+ require "active_record/fixture_set/render_context"
526
+ require "active_record/fixture_set/table_rows"
527
+
459
528
  #--
460
529
  # An instance of FixtureSet is normally stored in a single YAML file and
461
530
  # possibly in a folder with the same name.
@@ -467,39 +536,6 @@ module ActiveRecord
467
536
 
468
537
  cattr_accessor :all_loaded_fixtures, default: {}
469
538
 
470
- class ClassCache
471
- def initialize(class_names, config)
472
- @class_names = class_names.stringify_keys
473
- @config = config
474
-
475
- # Remove string values that aren't constants or subclasses of AR
476
- @class_names.delete_if do |klass_name, klass|
477
- !insert_class(@class_names, klass_name, klass)
478
- end
479
- end
480
-
481
- def [](fs_name)
482
- @class_names.fetch(fs_name) do
483
- klass = default_fixture_model(fs_name, @config).safe_constantize
484
- insert_class(@class_names, fs_name, klass)
485
- end
486
- end
487
-
488
- private
489
- def insert_class(class_names, name, klass)
490
- # We only want to deal with AR objects.
491
- if klass && klass < ActiveRecord::Base
492
- class_names[name] = klass
493
- else
494
- class_names[name] = nil
495
- end
496
- end
497
-
498
- def default_fixture_model(fs_name, config)
499
- ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
500
- end
501
- end
502
-
503
539
  class << self
504
540
  def default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
505
541
  config.pluralize_table_names ?
@@ -552,9 +588,9 @@ module ActiveRecord
552
588
  end
553
589
  end
554
590
 
555
- def create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
591
+ def create_fixtures(fixtures_directories, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
556
592
  fixture_set_names = Array(fixture_set_names).map(&:to_s)
557
- class_names = ClassCache.new class_names, config
593
+ class_names.stringify_keys!
558
594
 
559
595
  # FIXME: Apparently JK uses this.
560
596
  connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
@@ -565,7 +601,7 @@ module ActiveRecord
565
601
 
566
602
  if fixture_files_to_read.any?
567
603
  fixtures_map = read_and_insert(
568
- fixtures_directory,
604
+ Array(fixtures_directories),
569
605
  fixture_files_to_read,
570
606
  class_names,
571
607
  connection,
@@ -576,7 +612,8 @@ module ActiveRecord
576
612
  end
577
613
 
578
614
  # Returns a consistent, platform-independent identifier for +label+.
579
- # Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
615
+ #
616
+ # \Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
580
617
  def identify(label, column_type = :integer)
581
618
  if column_type == :uuid
582
619
  Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
@@ -585,29 +622,35 @@ module ActiveRecord
585
622
  end
586
623
  end
587
624
 
588
- def signed_global_id(fixture_set_name, label, column_type: :integer, **options)
589
- identifier = identify(label, column_type)
590
- model_name = default_fixture_model_name(fixture_set_name)
591
- uri = URI::GID.build([GlobalID.app, model_name, identifier, {}])
592
-
593
- SignedGlobalID.new(uri, **options)
625
+ # Returns a consistent, platform-independent hash representing a mapping
626
+ # between the label and the subcomponents of the provided composite key.
627
+ #
628
+ # Example:
629
+ #
630
+ # composite_identify("label", [:a, :b, :c]) # => { a: hash_1, b: hash_2, c: hash_3 }
631
+ def composite_identify(label, key)
632
+ key
633
+ .index_with
634
+ .with_index { |sub_key, index| (identify(label) << index) % MAX_ID }
635
+ .with_indifferent_access
594
636
  end
595
637
 
596
- # Superclass for the evaluation contexts used by ERB fixtures.
638
+ # Superclass for the evaluation contexts used by \ERB fixtures.
597
639
  def context_class
598
640
  @context_class ||= Class.new
599
641
  end
600
642
 
601
643
  private
602
- def read_and_insert(fixtures_directory, fixture_files, class_names, connection) # :nodoc:
644
+ def read_and_insert(fixtures_directories, fixture_files, class_names, connection) # :nodoc:
603
645
  fixtures_map = {}
646
+ directory_glob = "{#{fixtures_directories.join(",")}}"
604
647
  fixture_sets = fixture_files.map do |fixture_set_name|
605
648
  klass = class_names[fixture_set_name]
606
649
  fixtures_map[fixture_set_name] = new( # ActiveRecord::FixtureSet.new
607
650
  nil,
608
651
  fixture_set_name,
609
652
  klass,
610
- ::File.join(fixtures_directory, fixture_set_name)
653
+ ::File.join(directory_glob, fixture_set_name)
611
654
  )
612
655
  end
613
656
  update_all_loaded_fixtures(fixtures_map)
@@ -637,6 +680,8 @@ module ActiveRecord
637
680
 
638
681
  conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
639
682
 
683
+ check_all_foreign_keys_valid!(conn)
684
+
640
685
  # Cap primary key sequences to max(pk).
641
686
  if conn.respond_to?(:reset_pk_sequence!)
642
687
  set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
@@ -644,6 +689,16 @@ module ActiveRecord
644
689
  end
645
690
  end
646
691
 
692
+ def check_all_foreign_keys_valid!(conn)
693
+ return unless ActiveRecord.verify_foreign_keys_for_fixtures
694
+
695
+ begin
696
+ conn.check_all_foreign_keys_valid!
697
+ rescue ActiveRecord::StatementInvalid => e
698
+ raise "Foreign key violations found in your fixture data. Ensure you aren't referring to labels that don't exist on associations. Error from database:\n\n#{e.message}"
699
+ end
700
+ end
701
+
647
702
  def update_all_loaded_fixtures(fixtures_map) # :nodoc:
648
703
  all_loaded_fixtures.update(fixtures_map)
649
704
  end
@@ -657,7 +712,6 @@ module ActiveRecord
657
712
  @config = config
658
713
 
659
714
  self.model_class = class_name
660
-
661
715
  @fixtures = read_fixture_files(path)
662
716
 
663
717
  @table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
@@ -689,7 +743,6 @@ module ActiveRecord
689
743
  table_name,
690
744
  model_class: model_class,
691
745
  fixtures: fixtures,
692
- config: config,
693
746
  ).to_hash
694
747
  end
695
748
 
@@ -720,14 +773,18 @@ module ActiveRecord
720
773
  # Loads the fixtures from the YAML file at +path+.
721
774
  # If the file sets the +model_class+ and current instance value is not set,
722
775
  # it uses the file value.
776
+
723
777
  def read_fixture_files(path)
724
- yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
778
+ yaml_files = Dir["#{path}{.yml,/{**,*}/*.yml}"].select { |f|
725
779
  ::File.file?(f)
726
- } + [yaml_file_path(path)]
780
+ }
781
+
782
+ raise ArgumentError, "No fixture files found for #{@name}" if yaml_files.empty?
727
783
 
728
784
  yaml_files.each_with_object({}) do |file, fixtures|
729
785
  FixtureSet::File.open(file) do |fh|
730
786
  self.model_class ||= fh.model_class if fh.model_class
787
+ self.model_class ||= default_fixture_model_class
731
788
  self.ignored_fixtures ||= fh.ignored_fixtures
732
789
  fh.each do |fixture_name, row|
733
790
  fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
@@ -736,18 +793,19 @@ module ActiveRecord
736
793
  end
737
794
  end
738
795
 
739
- def yaml_file_path(path)
740
- "#{path}.yml"
796
+ def default_fixture_model_class
797
+ klass = ActiveRecord::FixtureSet.default_fixture_model_name(@name, @config).safe_constantize
798
+ klass if klass && klass < ActiveRecord::Base
741
799
  end
742
800
  end
743
801
 
744
- class Fixture #:nodoc:
802
+ class Fixture # :nodoc:
745
803
  include Enumerable
746
804
 
747
- class FixtureError < StandardError #:nodoc:
805
+ class FixtureError < StandardError # :nodoc:
748
806
  end
749
807
 
750
- class FormatError < FixtureError #:nodoc:
808
+ class FormatError < FixtureError # :nodoc:
751
809
  end
752
810
 
753
811
  attr_reader :model_class, :fixture
@@ -761,8 +819,8 @@ module ActiveRecord
761
819
  model_class.name if model_class
762
820
  end
763
821
 
764
- def each
765
- fixture.each { |item| yield item }
822
+ def each(&block)
823
+ fixture.each(&block)
766
824
  end
767
825
 
768
826
  def [](key)
@@ -774,7 +832,8 @@ module ActiveRecord
774
832
  def find
775
833
  raise FixtureClassNotFound, "No class attached to find." unless model_class
776
834
  object = model_class.unscoped do
777
- model_class.find(fixture[model_class.primary_key])
835
+ pk_clauses = fixture.slice(*Array(model_class.primary_key))
836
+ model_class.find_by!(pk_clauses)
778
837
  end
779
838
  # Fixtures can't be eagerly loaded
780
839
  object.instance_variable_set(:@strict_loading, false)
@@ -782,3 +841,5 @@ module ActiveRecord
782
841
  end
783
842
  end
784
843
  end
844
+
845
+ ActiveSupport.run_load_hooks :active_record_fixture_set, ActiveRecord::FixtureSet
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class FutureResult # :nodoc:
5
+ class Complete
6
+ attr_reader :result
7
+ delegate :empty?, :to_a, to: :result
8
+
9
+ def initialize(result)
10
+ @result = result
11
+ end
12
+
13
+ def pending?
14
+ false
15
+ end
16
+
17
+ def canceled?
18
+ false
19
+ end
20
+
21
+ def then(&block)
22
+ Promise::Complete.new(@result.then(&block))
23
+ end
24
+ end
25
+
26
+ class EventBuffer
27
+ def initialize(future_result, instrumenter)
28
+ @future_result = future_result
29
+ @instrumenter = instrumenter
30
+ @events = []
31
+ end
32
+
33
+ def instrument(name, payload = {}, &block)
34
+ event = @instrumenter.new_event(name, payload)
35
+ @events << event
36
+ event.record(&block)
37
+ end
38
+
39
+ def flush
40
+ events, @events = @events, []
41
+ events.each do |event|
42
+ event.payload[:lock_wait] = @future_result.lock_wait
43
+ ActiveSupport::Notifications.publish_event(event)
44
+ end
45
+ end
46
+ end
47
+
48
+ Canceled = Class.new(ActiveRecordError)
49
+
50
+ def self.wrap(result)
51
+ case result
52
+ when self, Complete
53
+ result
54
+ else
55
+ Complete.new(result)
56
+ end
57
+ end
58
+
59
+ delegate :empty?, :to_a, to: :result
60
+ delegate_missing_to :result
61
+
62
+ attr_reader :lock_wait
63
+
64
+ def initialize(pool, *args, **kwargs)
65
+ @mutex = Mutex.new
66
+
67
+ @session = nil
68
+ @pool = pool
69
+ @args = args
70
+ @kwargs = kwargs
71
+
72
+ @pending = true
73
+ @error = nil
74
+ @result = nil
75
+ @instrumenter = ActiveSupport::Notifications.instrumenter
76
+ @event_buffer = nil
77
+ end
78
+
79
+ def then(&block)
80
+ Promise.new(self, block)
81
+ end
82
+
83
+ def schedule!(session)
84
+ @session = session
85
+ @pool.schedule_query(self)
86
+ end
87
+
88
+ def execute!(connection)
89
+ execute_query(connection)
90
+ end
91
+
92
+ def cancel
93
+ @pending = false
94
+ @error = Canceled
95
+ self
96
+ end
97
+
98
+ def execute_or_skip
99
+ return unless pending?
100
+
101
+ @pool.with_connection do |connection|
102
+ return unless @mutex.try_lock
103
+ begin
104
+ if pending?
105
+ @event_buffer = EventBuffer.new(self, @instrumenter)
106
+ connection.with_instrumenter(@event_buffer) do
107
+ execute_query(connection, async: true)
108
+ end
109
+ end
110
+ ensure
111
+ @mutex.unlock
112
+ end
113
+ end
114
+ end
115
+
116
+ def result
117
+ execute_or_wait
118
+ @event_buffer&.flush
119
+
120
+ if canceled?
121
+ raise Canceled
122
+ elsif @error
123
+ raise @error
124
+ else
125
+ @result
126
+ end
127
+ end
128
+
129
+ def pending?
130
+ @pending && (!@session || @session.active?)
131
+ end
132
+
133
+ def canceled?
134
+ @session && !@session.active?
135
+ end
136
+
137
+ private
138
+ def execute_or_wait
139
+ if pending?
140
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
141
+ @mutex.synchronize do
142
+ if pending?
143
+ execute_query(@pool.connection)
144
+ else
145
+ @lock_wait = (Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) - start)
146
+ end
147
+ end
148
+ else
149
+ @lock_wait = 0.0
150
+ end
151
+ end
152
+
153
+ def execute_query(connection, async: false)
154
+ @result = exec_query(connection, *@args, **@kwargs, async: async)
155
+ rescue => error
156
+ @error = error
157
+ ensure
158
+ @pending = false
159
+ end
160
+
161
+ def exec_query(connection, *args, **kwargs)
162
+ connection.internal_exec_query(*args, **kwargs)
163
+ end
164
+
165
+ class SelectAll < FutureResult # :nodoc:
166
+ private
167
+ def exec_query(*, **)
168
+ super
169
+ rescue ::RangeError
170
+ ActiveRecord::Result.empty
171
+ end
172
+ end
173
+ end
174
+ end