activerecord 7.0.8.7 → 7.2.3

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 (283) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +781 -1777
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +30 -30
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +16 -13
  7. data/lib/active_record/association_relation.rb +2 -2
  8. data/lib/active_record/associations/alias_tracker.rb +31 -23
  9. data/lib/active_record/associations/association.rb +35 -12
  10. data/lib/active_record/associations/association_scope.rb +16 -9
  11. data/lib/active_record/associations/belongs_to_association.rb +40 -9
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
  13. data/lib/active_record/associations/builder/association.rb +3 -3
  14. data/lib/active_record/associations/builder/belongs_to.rb +22 -8
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
  16. data/lib/active_record/associations/builder/has_many.rb +3 -4
  17. data/lib/active_record/associations/builder/has_one.rb +3 -4
  18. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  19. data/lib/active_record/associations/collection_association.rb +35 -21
  20. data/lib/active_record/associations/collection_proxy.rb +29 -11
  21. data/lib/active_record/associations/errors.rb +265 -0
  22. data/lib/active_record/associations/foreign_association.rb +10 -3
  23. data/lib/active_record/associations/has_many_association.rb +21 -14
  24. data/lib/active_record/associations/has_many_through_association.rb +17 -7
  25. data/lib/active_record/associations/has_one_association.rb +10 -3
  26. data/lib/active_record/associations/join_dependency/join_association.rb +4 -3
  27. data/lib/active_record/associations/join_dependency.rb +10 -10
  28. data/lib/active_record/associations/nested_error.rb +47 -0
  29. data/lib/active_record/associations/preloader/association.rb +33 -8
  30. data/lib/active_record/associations/preloader/branch.rb +7 -1
  31. data/lib/active_record/associations/preloader/through_association.rb +1 -3
  32. data/lib/active_record/associations/preloader.rb +13 -10
  33. data/lib/active_record/associations/singular_association.rb +7 -1
  34. data/lib/active_record/associations/through_association.rb +22 -11
  35. data/lib/active_record/associations.rb +354 -485
  36. data/lib/active_record/attribute_assignment.rb +0 -4
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
  38. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  39. data/lib/active_record/attribute_methods/dirty.rb +53 -35
  40. data/lib/active_record/attribute_methods/primary_key.rb +45 -25
  41. data/lib/active_record/attribute_methods/query.rb +28 -16
  42. data/lib/active_record/attribute_methods/read.rb +8 -7
  43. data/lib/active_record/attribute_methods/serialization.rb +131 -32
  44. data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
  45. data/lib/active_record/attribute_methods/write.rb +6 -6
  46. data/lib/active_record/attribute_methods.rb +153 -33
  47. data/lib/active_record/attributes.rb +96 -71
  48. data/lib/active_record/autosave_association.rb +81 -39
  49. data/lib/active_record/base.rb +11 -7
  50. data/lib/active_record/callbacks.rb +11 -25
  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 -42
  54. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +123 -131
  55. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +343 -91
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +229 -64
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -63
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +142 -12
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +310 -129
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +539 -111
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +289 -128
  69. data/lib/active_record/connection_adapters/column.rb +9 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +26 -139
  72. data/lib/active_record/connection_adapters/mysql/quoting.rb +60 -55
  73. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  76. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +25 -13
  77. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  78. data/lib/active_record/connection_adapters/mysql2_adapter.rb +108 -68
  79. data/lib/active_record/connection_adapters/pool_config.rb +20 -10
  80. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +100 -43
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
  87. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
  88. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  89. data/lib/active_record/connection_adapters/postgresql/quoting.rb +65 -61
  90. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
  91. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
  92. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -2
  93. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -1
  94. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +371 -64
  95. data/lib/active_record/connection_adapters/postgresql_adapter.rb +374 -203
  96. data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
  97. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  98. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
  99. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -45
  100. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  101. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +14 -0
  102. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  103. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +51 -8
  104. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +298 -113
  105. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  106. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  107. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  108. data/lib/active_record/connection_adapters.rb +124 -1
  109. data/lib/active_record/connection_handling.rb +101 -105
  110. data/lib/active_record/core.rb +273 -178
  111. data/lib/active_record/counter_cache.rb +69 -35
  112. data/lib/active_record/database_configurations/connection_url_resolver.rb +10 -3
  113. data/lib/active_record/database_configurations/database_config.rb +26 -5
  114. data/lib/active_record/database_configurations/hash_config.rb +52 -34
  115. data/lib/active_record/database_configurations/url_config.rb +37 -12
  116. data/lib/active_record/database_configurations.rb +87 -34
  117. data/lib/active_record/delegated_type.rb +56 -27
  118. data/lib/active_record/deprecator.rb +7 -0
  119. data/lib/active_record/destroy_association_async_job.rb +3 -1
  120. data/lib/active_record/dynamic_matchers.rb +2 -2
  121. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  122. data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
  123. data/lib/active_record/encryption/config.rb +25 -1
  124. data/lib/active_record/encryption/configurable.rb +12 -19
  125. data/lib/active_record/encryption/context.rb +10 -3
  126. data/lib/active_record/encryption/contexts.rb +5 -1
  127. data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
  128. data/lib/active_record/encryption/encryptable_record.rb +46 -22
  129. data/lib/active_record/encryption/encrypted_attribute_type.rb +48 -13
  130. data/lib/active_record/encryption/encryptor.rb +35 -19
  131. data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
  132. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
  133. data/lib/active_record/encryption/key_generator.rb +12 -1
  134. data/lib/active_record/encryption/key_provider.rb +1 -1
  135. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  136. data/lib/active_record/encryption/message_serializer.rb +6 -0
  137. data/lib/active_record/encryption/null_encryptor.rb +4 -0
  138. data/lib/active_record/encryption/properties.rb +3 -3
  139. data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
  140. data/lib/active_record/encryption/scheme.rb +22 -21
  141. data/lib/active_record/encryption.rb +3 -0
  142. data/lib/active_record/enum.rb +130 -28
  143. data/lib/active_record/errors.rb +154 -34
  144. data/lib/active_record/explain.rb +21 -12
  145. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  146. data/lib/active_record/fixture_set/render_context.rb +2 -0
  147. data/lib/active_record/fixture_set/table_row.rb +48 -10
  148. data/lib/active_record/fixtures.rb +167 -97
  149. data/lib/active_record/future_result.rb +47 -8
  150. data/lib/active_record/gem_version.rb +4 -4
  151. data/lib/active_record/inheritance.rb +34 -18
  152. data/lib/active_record/insert_all.rb +72 -22
  153. data/lib/active_record/integration.rb +11 -8
  154. data/lib/active_record/internal_metadata.rb +124 -20
  155. data/lib/active_record/locking/optimistic.rb +8 -7
  156. data/lib/active_record/locking/pessimistic.rb +5 -2
  157. data/lib/active_record/log_subscriber.rb +18 -22
  158. data/lib/active_record/marshalling.rb +59 -0
  159. data/lib/active_record/message_pack.rb +124 -0
  160. data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
  161. data/lib/active_record/middleware/database_selector.rb +6 -8
  162. data/lib/active_record/middleware/shard_selector.rb +3 -1
  163. data/lib/active_record/migration/command_recorder.rb +106 -8
  164. data/lib/active_record/migration/compatibility.rb +147 -5
  165. data/lib/active_record/migration/default_strategy.rb +22 -0
  166. data/lib/active_record/migration/execution_strategy.rb +19 -0
  167. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  168. data/lib/active_record/migration.rb +236 -118
  169. data/lib/active_record/model_schema.rb +90 -102
  170. data/lib/active_record/nested_attributes.rb +48 -11
  171. data/lib/active_record/normalization.rb +163 -0
  172. data/lib/active_record/persistence.rb +168 -339
  173. data/lib/active_record/promise.rb +84 -0
  174. data/lib/active_record/query_cache.rb +18 -25
  175. data/lib/active_record/query_logs.rb +96 -52
  176. data/lib/active_record/query_logs_formatter.rb +41 -0
  177. data/lib/active_record/querying.rb +35 -10
  178. data/lib/active_record/railtie.rb +131 -87
  179. data/lib/active_record/railties/controller_runtime.rb +22 -7
  180. data/lib/active_record/railties/databases.rake +147 -155
  181. data/lib/active_record/railties/job_runtime.rb +23 -0
  182. data/lib/active_record/readonly_attributes.rb +32 -5
  183. data/lib/active_record/reflection.rb +267 -69
  184. data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
  185. data/lib/active_record/relation/batches.rb +198 -63
  186. data/lib/active_record/relation/calculations.rb +270 -108
  187. data/lib/active_record/relation/delegation.rb +30 -19
  188. data/lib/active_record/relation/finder_methods.rb +97 -21
  189. data/lib/active_record/relation/merger.rb +6 -6
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +20 -3
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  193. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  194. data/lib/active_record/relation/predicate_builder.rb +28 -16
  195. data/lib/active_record/relation/query_attribute.rb +3 -2
  196. data/lib/active_record/relation/query_methods.rb +585 -109
  197. data/lib/active_record/relation/record_fetch_warning.rb +3 -0
  198. data/lib/active_record/relation/spawn_methods.rb +5 -4
  199. data/lib/active_record/relation/where_clause.rb +15 -21
  200. data/lib/active_record/relation.rb +592 -92
  201. data/lib/active_record/result.rb +49 -48
  202. data/lib/active_record/runtime_registry.rb +63 -1
  203. data/lib/active_record/sanitization.rb +70 -25
  204. data/lib/active_record/schema.rb +8 -7
  205. data/lib/active_record/schema_dumper.rb +90 -23
  206. data/lib/active_record/schema_migration.rb +75 -24
  207. data/lib/active_record/scoping/default.rb +15 -5
  208. data/lib/active_record/scoping/named.rb +3 -2
  209. data/lib/active_record/scoping.rb +2 -1
  210. data/lib/active_record/secure_password.rb +60 -0
  211. data/lib/active_record/secure_token.rb +21 -3
  212. data/lib/active_record/signed_id.rb +33 -11
  213. data/lib/active_record/statement_cache.rb +7 -7
  214. data/lib/active_record/store.rb +8 -8
  215. data/lib/active_record/suppressor.rb +3 -1
  216. data/lib/active_record/table_metadata.rb +1 -1
  217. data/lib/active_record/tasks/database_tasks.rb +190 -118
  218. data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
  219. data/lib/active_record/tasks/postgresql_database_tasks.rb +23 -13
  220. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
  221. data/lib/active_record/test_fixtures.rb +170 -155
  222. data/lib/active_record/testing/query_assertions.rb +121 -0
  223. data/lib/active_record/timestamp.rb +31 -17
  224. data/lib/active_record/token_for.rb +123 -0
  225. data/lib/active_record/touch_later.rb +12 -7
  226. data/lib/active_record/transaction.rb +132 -0
  227. data/lib/active_record/transactions.rb +108 -24
  228. data/lib/active_record/translation.rb +0 -2
  229. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  230. data/lib/active_record/type/internal/timezone.rb +7 -2
  231. data/lib/active_record/type/serialized.rb +1 -3
  232. data/lib/active_record/type/time.rb +4 -0
  233. data/lib/active_record/type_caster/connection.rb +4 -4
  234. data/lib/active_record/validations/absence.rb +1 -1
  235. data/lib/active_record/validations/associated.rb +9 -3
  236. data/lib/active_record/validations/numericality.rb +5 -4
  237. data/lib/active_record/validations/presence.rb +5 -28
  238. data/lib/active_record/validations/uniqueness.rb +61 -11
  239. data/lib/active_record/validations.rb +12 -5
  240. data/lib/active_record/version.rb +1 -1
  241. data/lib/active_record.rb +247 -33
  242. data/lib/arel/alias_predication.rb +1 -1
  243. data/lib/arel/collectors/bind.rb +3 -1
  244. data/lib/arel/collectors/composite.rb +7 -0
  245. data/lib/arel/collectors/sql_string.rb +1 -1
  246. data/lib/arel/collectors/substitute_binds.rb +1 -1
  247. data/lib/arel/crud.rb +2 -0
  248. data/lib/arel/delete_manager.rb +5 -0
  249. data/lib/arel/errors.rb +10 -0
  250. data/lib/arel/factory_methods.rb +4 -0
  251. data/lib/arel/nodes/binary.rb +6 -7
  252. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  253. data/lib/arel/nodes/cte.rb +36 -0
  254. data/lib/arel/nodes/delete_statement.rb +4 -2
  255. data/lib/arel/nodes/fragments.rb +35 -0
  256. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  257. data/lib/arel/nodes/leading_join.rb +8 -0
  258. data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
  259. data/lib/arel/nodes/node.rb +115 -5
  260. data/lib/arel/nodes/sql_literal.rb +13 -0
  261. data/lib/arel/nodes/table_alias.rb +4 -0
  262. data/lib/arel/nodes/update_statement.rb +4 -2
  263. data/lib/arel/nodes.rb +6 -2
  264. data/lib/arel/predications.rb +3 -1
  265. data/lib/arel/select_manager.rb +7 -3
  266. data/lib/arel/table.rb +9 -5
  267. data/lib/arel/tree_manager.rb +8 -3
  268. data/lib/arel/update_manager.rb +7 -1
  269. data/lib/arel/visitors/dot.rb +3 -0
  270. data/lib/arel/visitors/mysql.rb +17 -5
  271. data/lib/arel/visitors/postgresql.rb +1 -12
  272. data/lib/arel/visitors/sqlite.rb +25 -0
  273. data/lib/arel/visitors/to_sql.rb +114 -34
  274. data/lib/arel/visitors/visitor.rb +2 -2
  275. data/lib/arel.rb +21 -3
  276. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  277. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  278. data/lib/rails/generators/active_record/migration.rb +3 -1
  279. data/lib/rails/generators/active_record/model/USAGE +113 -0
  280. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  281. metadata +56 -17
  282. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  283. data/lib/active_record/null_relation.rb +0 -63
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
+ # = Active Record Connection Handling
4
5
  module ConnectionHandling
5
6
  RAILS_ENV = -> { (Rails.env if defined?(Rails.env)) || ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence }
6
7
  DEFAULT_ENV = -> { RAILS_ENV.call || "default_env" }
@@ -38,7 +39,7 @@ module ActiveRecord
38
39
  # )
39
40
  #
40
41
  # In case {ActiveRecord::Base.configurations}[rdoc-ref:Core.configurations]
41
- # is set (Rails automatically loads the contents of config/database.yml into it),
42
+ # is set (\Rails automatically loads the contents of config/database.yml into it),
42
43
  # a symbol can also be given as argument, representing a key in the
43
44
  # configuration hash:
44
45
  #
@@ -48,16 +49,15 @@ module ActiveRecord
48
49
  # may be returned on an error.
49
50
  def establish_connection(config_or_env = nil)
50
51
  config_or_env ||= DEFAULT_ENV.call.to_sym
51
- db_config, owner_name = resolve_config_for_connection(config_or_env)
52
- connection_handler.establish_connection(db_config, owner_name: owner_name, role: current_role, shard: current_shard)
52
+ db_config = resolve_config_for_connection(config_or_env)
53
+ connection_handler.establish_connection(db_config, owner_name: self, role: current_role, shard: current_shard)
53
54
  end
54
55
 
55
56
  # Connects a model to the databases specified. The +database+ keyword
56
57
  # takes a hash consisting of a +role+ and a +database_key+.
57
58
  #
58
- # This will create a connection handler for switching between connections,
59
- # look up the config hash using the +database_key+ and finally
60
- # establishes a connection to that config.
59
+ # This will look up the database config using the +database_key+ and
60
+ # establish a connection to that config.
61
61
  #
62
62
  # class AnimalsModel < ApplicationRecord
63
63
  # self.abstract_class = true
@@ -66,7 +66,7 @@ module ActiveRecord
66
66
  # end
67
67
  #
68
68
  # +connects_to+ also supports horizontal sharding. The horizontal sharding API
69
- # also supports read replicas. Connect a model to a list of shards like this:
69
+ # supports read replicas as well. You can connect a model to a list of shards like this:
70
70
  #
71
71
  # class AnimalsModel < ApplicationRecord
72
72
  # self.abstract_class = true
@@ -87,21 +87,18 @@ module ActiveRecord
87
87
 
88
88
  connections = []
89
89
 
90
- database.each do |role, database_key|
91
- db_config, owner_name = resolve_config_for_connection(database_key)
92
- handler = lookup_connection_handler(role.to_sym)
93
-
94
- self.connection_class = true
95
- connections << handler.establish_connection(db_config, owner_name: owner_name, role: role)
90
+ if shards.empty?
91
+ shards[:default] = database
96
92
  end
97
93
 
94
+ self.default_shard = shards.keys.first
95
+
98
96
  shards.each do |shard, database_keys|
99
97
  database_keys.each do |role, database_key|
100
- db_config, owner_name = resolve_config_for_connection(database_key)
101
- handler = lookup_connection_handler(role.to_sym)
98
+ db_config = resolve_config_for_connection(database_key)
102
99
 
103
100
  self.connection_class = true
104
- connections << handler.establish_connection(db_config, owner_name: owner_name, role: role, shard: shard.to_sym)
101
+ connections << connection_handler.establish_connection(db_config, owner_name: self, role: role, shard: shard.to_sym)
105
102
  end
106
103
  end
107
104
 
@@ -135,18 +132,12 @@ module ActiveRecord
135
132
  # Dog.first # finds first Dog record stored on the shard one replica
136
133
  # end
137
134
  def connected_to(role: nil, shard: nil, prevent_writes: false, &blk)
138
- if ActiveRecord.legacy_connection_handling
139
- if self != Base
140
- raise NotImplementedError, "`connected_to` can only be called on ActiveRecord::Base with legacy connection handling."
141
- end
142
- else
143
- if self != Base && !abstract_class
144
- raise NotImplementedError, "calling `connected_to` is only allowed on ActiveRecord::Base or abstract classes."
145
- end
135
+ if self != Base && !abstract_class
136
+ raise NotImplementedError, "calling `connected_to` is only allowed on ActiveRecord::Base or abstract classes."
137
+ end
146
138
 
147
- if name != connection_specification_name && !primary_class?
148
- raise NotImplementedError, "calling `connected_to` is only allowed on the abstract class that established the connection."
149
- end
139
+ if !connection_class? && !primary_class?
140
+ raise NotImplementedError, "calling `connected_to` is only allowed on the abstract class that established the connection."
150
141
  end
151
142
 
152
143
  unless role || shard
@@ -172,10 +163,6 @@ module ActiveRecord
172
163
  def connected_to_many(*classes, role:, shard: nil, prevent_writes: false)
173
164
  classes = classes.flatten
174
165
 
175
- if ActiveRecord.legacy_connection_handling
176
- raise NotImplementedError, "connected_to_many is not available with legacy connection handling"
177
- end
178
-
179
166
  if self != Base || classes.include?(Base)
180
167
  raise NotImplementedError, "connected_to_many can only be called on ActiveRecord::Base."
181
168
  end
@@ -183,9 +170,11 @@ module ActiveRecord
183
170
  prevent_writes = true if role == ActiveRecord.reading_role
184
171
 
185
172
  append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: classes)
186
- yield
187
- ensure
188
- connected_to_stack.pop
173
+ begin
174
+ yield
175
+ ensure
176
+ connected_to_stack.pop
177
+ end
189
178
  end
190
179
 
191
180
  # Use a specified connection.
@@ -196,10 +185,6 @@ module ActiveRecord
196
185
  # It is not recommended to use this method in a request since it
197
186
  # does not yield to a block like +connected_to+.
198
187
  def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
199
- if ActiveRecord.legacy_connection_handling
200
- raise NotImplementedError, "`connecting_to` is not available with `legacy_connection_handling`."
201
- end
202
-
203
188
  prevent_writes = true if role == ActiveRecord.reading_role
204
189
 
205
190
  append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
@@ -236,55 +221,88 @@ module ActiveRecord
236
221
  # See +READ_QUERY+ for the queries that are blocked by this
237
222
  # method.
238
223
  def while_preventing_writes(enabled = true, &block)
239
- if ActiveRecord.legacy_connection_handling
240
- connection_handler.while_preventing_writes(enabled, &block)
241
- else
242
- connected_to(role: current_role, prevent_writes: enabled, &block)
243
- end
224
+ connected_to(role: current_role, prevent_writes: enabled, &block)
244
225
  end
245
226
 
246
- # Returns true if role is the current connected role.
227
+ # Returns true if role is the current connected role and/or
228
+ # current connected shard. If no shard is passed, the default will be
229
+ # used.
247
230
  #
248
231
  # ActiveRecord::Base.connected_to(role: :writing) do
249
232
  # ActiveRecord::Base.connected_to?(role: :writing) #=> true
250
233
  # ActiveRecord::Base.connected_to?(role: :reading) #=> false
251
234
  # end
235
+ #
236
+ # ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one) do
237
+ # ActiveRecord::Base.connected_to?(role: :reading, shard: :shard_one) #=> true
238
+ # ActiveRecord::Base.connected_to?(role: :reading, shard: :default) #=> false
239
+ # ActiveRecord::Base.connected_to?(role: :writing, shard: :shard_one) #=> true
240
+ # end
252
241
  def connected_to?(role:, shard: ActiveRecord::Base.default_shard)
253
242
  current_role == role.to_sym && current_shard == shard.to_sym
254
243
  end
255
244
 
256
- def lookup_connection_handler(handler_key) # :nodoc:
257
- if ActiveRecord.legacy_connection_handling
258
- handler_key ||= ActiveRecord.writing_role
259
- connection_handlers[handler_key] ||= ActiveRecord::ConnectionAdapters::ConnectionHandler.new
260
- else
261
- ActiveRecord::Base.connection_handler
262
- end
263
- end
264
-
265
245
  # Clears the query cache for all connections associated with the current thread.
266
246
  def clear_query_caches_for_current_thread
267
- if ActiveRecord.legacy_connection_handling
268
- ActiveRecord::Base.connection_handlers.each_value do |handler|
269
- clear_on_handler(handler)
270
- end
271
- else
272
- clear_on_handler(ActiveRecord::Base.connection_handler)
247
+ connection_handler.each_connection_pool do |pool|
248
+ pool.clear_query_cache
273
249
  end
274
250
  end
275
251
 
276
252
  # Returns the connection currently associated with the class. This can
277
253
  # also be used to "borrow" the connection to do database work unrelated
278
254
  # to any of the specific Active Records.
255
+ # The connection will remain leased for the entire duration of the request
256
+ # or job, or until +#release_connection+ is called.
257
+ def lease_connection
258
+ connection_pool.lease_connection
259
+ end
260
+
261
+ # Soft deprecated. Use +#with_connection+ or +#lease_connection+ instead.
279
262
  def connection
280
- retrieve_connection
263
+ pool = connection_pool
264
+ if pool.permanent_lease?
265
+ case ActiveRecord.permanent_connection_checkout
266
+ when :deprecated
267
+ ActiveRecord.deprecator.warn <<~MESSAGE
268
+ Called deprecated `ActiveRecord::Base.connection` method.
269
+
270
+ Either use `with_connection` or `lease_connection`.
271
+ MESSAGE
272
+ when :disallowed
273
+ raise ActiveRecordError, <<~MESSAGE
274
+ Called deprecated `ActiveRecord::Base.connection` method.
275
+
276
+ Either use `with_connection` or `lease_connection`.
277
+ MESSAGE
278
+ end
279
+ pool.lease_connection
280
+ else
281
+ pool.active_connection
282
+ end
283
+ end
284
+
285
+ # Return the currently leased connection into the pool
286
+ def release_connection
287
+ connection_pool.release_connection
288
+ end
289
+
290
+ # Checkouts a connection from the pool, yield it and then check it back in.
291
+ # If a connection was already leased via #lease_connection or a parent call to
292
+ # #with_connection, that same connection is yieled.
293
+ # If #lease_connection is called inside the block, the connection won't be checked
294
+ # back in.
295
+ # If #connection is called inside the block, the connection won't be checked back in
296
+ # unless the +prevent_permanent_checkout+ argument is set to +true+.
297
+ def with_connection(prevent_permanent_checkout: false, &block)
298
+ connection_pool.with_connection(prevent_permanent_checkout: prevent_permanent_checkout, &block)
281
299
  end
282
300
 
283
301
  attr_writer :connection_specification_name
284
302
 
285
- # Return the connection specification name from the current class or its parent.
303
+ # Returns the connection specification name from the current class or its parent.
286
304
  def connection_specification_name
287
- if !defined?(@connection_specification_name) || @connection_specification_name.nil?
305
+ if @connection_specification_name.nil?
288
306
  return self == Base ? Base.name : superclass.connection_specification_name
289
307
  end
290
308
  @connection_specification_name
@@ -298,15 +316,19 @@ module ActiveRecord
298
316
  #
299
317
  # ActiveRecord::Base.connection_db_config
300
318
  # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
301
- # @name="primary", @config={pool: 5, timeout: 5000, database: "db/development.sqlite3", adapter: "sqlite3"}>
319
+ # @name="primary", @config={pool: 5, timeout: 5000, database: "storage/development.sqlite3", adapter: "sqlite3"}>
302
320
  #
303
321
  # Use only for reading.
304
322
  def connection_db_config
305
323
  connection_pool.db_config
306
324
  end
307
325
 
326
+ def adapter_class # :nodoc:
327
+ connection_pool.db_config.adapter_class
328
+ end
329
+
308
330
  def connection_pool
309
- connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard) || raise(ConnectionNotEstablished)
331
+ connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard, strict: true)
310
332
  end
311
333
 
312
334
  def retrieve_connection
@@ -318,8 +340,9 @@ module ActiveRecord
318
340
  connection_handler.connected?(connection_specification_name, role: current_role, shard: current_shard)
319
341
  end
320
342
 
321
- def remove_connection(name = nil)
322
- name ||= @connection_specification_name if defined?(@connection_specification_name)
343
+ def remove_connection
344
+ name = @connection_specification_name if defined?(@connection_specification_name)
345
+
323
346
  # if removing a connection that has a pool, we reset the
324
347
  # connection_specification_name so it will use the parent
325
348
  # pool.
@@ -330,53 +353,35 @@ module ActiveRecord
330
353
  connection_handler.remove_connection_pool(name, role: current_role, shard: current_shard)
331
354
  end
332
355
 
333
- def clear_cache! # :nodoc:
334
- connection.schema_cache.clear!
356
+ def schema_cache # :nodoc:
357
+ connection_pool.schema_cache
335
358
  end
336
359
 
337
- delegate :clear_active_connections!, :clear_reloadable_connections!,
338
- :clear_all_connections!, :flush_idle_connections!, to: :connection_handler
360
+ def clear_cache! # :nodoc:
361
+ connection_pool.schema_cache.clear!
362
+ end
339
363
 
340
364
  private
341
- def clear_on_handler(handler)
342
- handler.all_connection_pools.each do |pool|
343
- pool.connection.clear_query_cache if pool.active_connection?
344
- end
345
- end
346
-
347
365
  def resolve_config_for_connection(config_or_env)
348
366
  raise "Anonymous class is not allowed." unless name
349
367
 
350
- owner_name = primary_class? ? Base.name : name
351
- self.connection_specification_name = owner_name
368
+ connection_name = primary_class? ? Base.name : name
369
+ self.connection_specification_name = connection_name
352
370
 
353
- db_config = Base.configurations.resolve(config_or_env)
354
- [db_config, self]
355
- end
356
-
357
- def with_handler(handler_key, &blk)
358
- handler = lookup_connection_handler(handler_key)
359
- swap_connection_handler(handler, &blk)
371
+ Base.configurations.resolve(config_or_env)
360
372
  end
361
373
 
362
374
  def with_role_and_shard(role, shard, prevent_writes)
363
375
  prevent_writes = true if role == ActiveRecord.reading_role
364
376
 
365
- if ActiveRecord.legacy_connection_handling
366
- with_handler(role.to_sym) do
367
- connection_handler.while_preventing_writes(prevent_writes) do
368
- append_to_connected_to_stack(shard: shard, klasses: [self])
369
- yield
370
- end
371
- end
372
- else
373
- append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
377
+ append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
378
+ begin
374
379
  return_value = yield
375
380
  return_value.load if return_value.is_a? ActiveRecord::Relation
376
381
  return_value
382
+ ensure
383
+ self.connected_to_stack.pop
377
384
  end
378
- ensure
379
- self.connected_to_stack.pop
380
385
  end
381
386
 
382
387
  def append_to_connected_to_stack(entry)
@@ -386,14 +391,5 @@ module ActiveRecord
386
391
 
387
392
  connected_to_stack << entry
388
393
  end
389
-
390
- def swap_connection_handler(handler, &blk) # :nodoc:
391
- old_handler, ActiveRecord::Base.connection_handler = ActiveRecord::Base.connection_handler, handler
392
- return_value = yield
393
- return_value.load if return_value.is_a? ActiveRecord::Relation
394
- return_value
395
- ensure
396
- ActiveRecord::Base.connection_handler = old_handler
397
- end
398
394
  end
399
395
  end