activerecord 7.0.8.1 → 7.2.2.1

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 (279) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +642 -1925
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +29 -29
  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 +25 -19
  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 +23 -8
  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 +26 -14
  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 +30 -27
  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 +148 -33
  47. data/lib/active_record/attributes.rb +64 -50
  48. data/lib/active_record/autosave_association.rb +69 -37
  49. data/lib/active_record/base.rb +9 -5
  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 +323 -88
  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 +217 -63
  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 +137 -11
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +307 -129
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +510 -111
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +278 -125
  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 +53 -54
  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 +101 -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 +151 -2
  93. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
  94. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +370 -63
  95. data/lib/active_record/connection_adapters/postgresql_adapter.rb +367 -201
  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 +45 -46
  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 +50 -8
  104. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -110
  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 +96 -104
  110. data/lib/active_record/core.rb +251 -176
  111. data/lib/active_record/counter_cache.rb +68 -34
  112. data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -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 +39 -10
  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 +45 -21
  129. data/lib/active_record/encryption/encrypted_attribute_type.rb +47 -12
  130. data/lib/active_record/encryption/encryptor.rb +18 -3
  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 +129 -28
  143. data/lib/active_record/errors.rb +151 -31
  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 +29 -8
  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 +3 -3
  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 +234 -117
  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 +92 -52
  176. data/lib/active_record/query_logs_formatter.rb +41 -0
  177. data/lib/active_record/querying.rb +33 -8
  178. data/lib/active_record/railtie.rb +129 -85
  179. data/lib/active_record/railties/controller_runtime.rb +22 -7
  180. data/lib/active_record/railties/databases.rake +145 -154
  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 +250 -93
  187. data/lib/active_record/relation/delegation.rb +30 -19
  188. data/lib/active_record/relation/finder_methods.rb +93 -18
  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 +18 -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 +2 -1
  196. data/lib/active_record/relation/query_methods.rb +576 -107
  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 +7 -19
  200. data/lib/active_record/relation.rb +580 -90
  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 +63 -14
  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 +27 -6
  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 +16 -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 +106 -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 +2 -0
  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/errors.rb +10 -0
  248. data/lib/arel/factory_methods.rb +4 -0
  249. data/lib/arel/nodes/binary.rb +6 -7
  250. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  251. data/lib/arel/nodes/cte.rb +36 -0
  252. data/lib/arel/nodes/fragments.rb +35 -0
  253. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  254. data/lib/arel/nodes/leading_join.rb +8 -0
  255. data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
  256. data/lib/arel/nodes/node.rb +115 -5
  257. data/lib/arel/nodes/sql_literal.rb +13 -0
  258. data/lib/arel/nodes/table_alias.rb +4 -0
  259. data/lib/arel/nodes.rb +6 -2
  260. data/lib/arel/predications.rb +3 -1
  261. data/lib/arel/select_manager.rb +1 -1
  262. data/lib/arel/table.rb +9 -5
  263. data/lib/arel/tree_manager.rb +8 -3
  264. data/lib/arel/update_manager.rb +2 -1
  265. data/lib/arel/visitors/dot.rb +1 -0
  266. data/lib/arel/visitors/mysql.rb +17 -5
  267. data/lib/arel/visitors/postgresql.rb +1 -12
  268. data/lib/arel/visitors/sqlite.rb +25 -0
  269. data/lib/arel/visitors/to_sql.rb +112 -34
  270. data/lib/arel/visitors/visitor.rb +2 -2
  271. data/lib/arel.rb +21 -3
  272. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  273. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  274. data/lib/rails/generators/active_record/migration.rb +3 -1
  275. data/lib/rails/generators/active_record/model/USAGE +113 -0
  276. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  277. metadata +59 -17
  278. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  279. 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
@@ -196,10 +183,6 @@ module ActiveRecord
196
183
  # It is not recommended to use this method in a request since it
197
184
  # does not yield to a block like +connected_to+.
198
185
  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
186
  prevent_writes = true if role == ActiveRecord.reading_role
204
187
 
205
188
  append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
@@ -236,55 +219,88 @@ module ActiveRecord
236
219
  # See +READ_QUERY+ for the queries that are blocked by this
237
220
  # method.
238
221
  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
222
+ connected_to(role: current_role, prevent_writes: enabled, &block)
244
223
  end
245
224
 
246
- # Returns true if role is the current connected role.
225
+ # Returns true if role is the current connected role and/or
226
+ # current connected shard. If no shard is passed, the default will be
227
+ # used.
247
228
  #
248
229
  # ActiveRecord::Base.connected_to(role: :writing) do
249
230
  # ActiveRecord::Base.connected_to?(role: :writing) #=> true
250
231
  # ActiveRecord::Base.connected_to?(role: :reading) #=> false
251
232
  # end
233
+ #
234
+ # ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one) do
235
+ # ActiveRecord::Base.connected_to?(role: :reading, shard: :shard_one) #=> true
236
+ # ActiveRecord::Base.connected_to?(role: :reading, shard: :default) #=> false
237
+ # ActiveRecord::Base.connected_to?(role: :writing, shard: :shard_one) #=> true
238
+ # end
252
239
  def connected_to?(role:, shard: ActiveRecord::Base.default_shard)
253
240
  current_role == role.to_sym && current_shard == shard.to_sym
254
241
  end
255
242
 
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
243
  # Clears the query cache for all connections associated with the current thread.
266
244
  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)
245
+ connection_handler.each_connection_pool do |pool|
246
+ pool.clear_query_cache
273
247
  end
274
248
  end
275
249
 
276
250
  # Returns the connection currently associated with the class. This can
277
251
  # also be used to "borrow" the connection to do database work unrelated
278
252
  # to any of the specific Active Records.
253
+ # The connection will remain leased for the entire duration of the request
254
+ # or job, or until +#release_connection+ is called.
255
+ def lease_connection
256
+ connection_pool.lease_connection
257
+ end
258
+
259
+ # Soft deprecated. Use +#with_connection+ or +#lease_connection+ instead.
279
260
  def connection
280
- retrieve_connection
261
+ pool = connection_pool
262
+ if pool.permanent_lease?
263
+ case ActiveRecord.permanent_connection_checkout
264
+ when :deprecated
265
+ ActiveRecord.deprecator.warn <<~MESSAGE
266
+ Called deprecated `ActiveRecord::Base.connection` method.
267
+
268
+ Either use `with_connection` or `lease_connection`.
269
+ MESSAGE
270
+ when :disallowed
271
+ raise ActiveRecordError, <<~MESSAGE
272
+ Called deprecated `ActiveRecord::Base.connection` method.
273
+
274
+ Either use `with_connection` or `lease_connection`.
275
+ MESSAGE
276
+ end
277
+ pool.lease_connection
278
+ else
279
+ pool.active_connection
280
+ end
281
+ end
282
+
283
+ # Return the currently leased connection into the pool
284
+ def release_connection
285
+ connection_pool.release_connection
286
+ end
287
+
288
+ # Checkouts a connection from the pool, yield it and then check it back in.
289
+ # If a connection was already leased via #lease_connection or a parent call to
290
+ # #with_connection, that same connection is yieled.
291
+ # If #lease_connection is called inside the block, the connection won't be checked
292
+ # back in.
293
+ # If #connection is called inside the block, the connection won't be checked back in
294
+ # unless the +prevent_permanent_checkout+ argument is set to +true+.
295
+ def with_connection(prevent_permanent_checkout: false, &block)
296
+ connection_pool.with_connection(prevent_permanent_checkout: prevent_permanent_checkout, &block)
281
297
  end
282
298
 
283
299
  attr_writer :connection_specification_name
284
300
 
285
- # Return the connection specification name from the current class or its parent.
301
+ # Returns the connection specification name from the current class or its parent.
286
302
  def connection_specification_name
287
- if !defined?(@connection_specification_name) || @connection_specification_name.nil?
303
+ if @connection_specification_name.nil?
288
304
  return self == Base ? Base.name : superclass.connection_specification_name
289
305
  end
290
306
  @connection_specification_name
@@ -298,15 +314,19 @@ module ActiveRecord
298
314
  #
299
315
  # ActiveRecord::Base.connection_db_config
300
316
  # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
301
- # @name="primary", @config={pool: 5, timeout: 5000, database: "db/development.sqlite3", adapter: "sqlite3"}>
317
+ # @name="primary", @config={pool: 5, timeout: 5000, database: "storage/development.sqlite3", adapter: "sqlite3"}>
302
318
  #
303
319
  # Use only for reading.
304
320
  def connection_db_config
305
321
  connection_pool.db_config
306
322
  end
307
323
 
324
+ def adapter_class # :nodoc:
325
+ connection_pool.db_config.adapter_class
326
+ end
327
+
308
328
  def connection_pool
309
- connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard) || raise(ConnectionNotEstablished)
329
+ connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard, strict: true)
310
330
  end
311
331
 
312
332
  def retrieve_connection
@@ -318,8 +338,9 @@ module ActiveRecord
318
338
  connection_handler.connected?(connection_specification_name, role: current_role, shard: current_shard)
319
339
  end
320
340
 
321
- def remove_connection(name = nil)
322
- name ||= @connection_specification_name if defined?(@connection_specification_name)
341
+ def remove_connection
342
+ name = @connection_specification_name if defined?(@connection_specification_name)
343
+
323
344
  # if removing a connection that has a pool, we reset the
324
345
  # connection_specification_name so it will use the parent
325
346
  # pool.
@@ -330,51 +351,31 @@ module ActiveRecord
330
351
  connection_handler.remove_connection_pool(name, role: current_role, shard: current_shard)
331
352
  end
332
353
 
333
- def clear_cache! # :nodoc:
334
- connection.schema_cache.clear!
354
+ def schema_cache # :nodoc:
355
+ connection_pool.schema_cache
335
356
  end
336
357
 
337
- delegate :clear_active_connections!, :clear_reloadable_connections!,
338
- :clear_all_connections!, :flush_idle_connections!, to: :connection_handler
358
+ def clear_cache! # :nodoc:
359
+ connection_pool.schema_cache.clear!
360
+ end
339
361
 
340
362
  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
363
  def resolve_config_for_connection(config_or_env)
348
364
  raise "Anonymous class is not allowed." unless name
349
365
 
350
- owner_name = primary_class? ? Base.name : name
351
- self.connection_specification_name = owner_name
366
+ connection_name = primary_class? ? Base.name : name
367
+ self.connection_specification_name = connection_name
352
368
 
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)
369
+ Base.configurations.resolve(config_or_env)
360
370
  end
361
371
 
362
372
  def with_role_and_shard(role, shard, prevent_writes)
363
373
  prevent_writes = true if role == ActiveRecord.reading_role
364
374
 
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])
374
- return_value = yield
375
- return_value.load if return_value.is_a? ActiveRecord::Relation
376
- return_value
377
- end
375
+ append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
376
+ return_value = yield
377
+ return_value.load if return_value.is_a? ActiveRecord::Relation
378
+ return_value
378
379
  ensure
379
380
  self.connected_to_stack.pop
380
381
  end
@@ -386,14 +387,5 @@ module ActiveRecord
386
387
 
387
388
  connected_to_stack << entry
388
389
  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
390
  end
399
391
  end