activerecord 7.0.8.6 → 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 +631 -1939
  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 +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 +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 +56 -14
  278. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  279. data/lib/active_record/null_relation.rb +0 -63
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/deprecation"
4
+
3
5
  module ActiveRecord
6
+ include ActiveSupport::Deprecation::DeprecatedConstantAccessor
7
+
4
8
  # = Active Record Errors
5
9
  #
6
10
  # Generic Active Record exception class.
7
11
  class ActiveRecordError < StandardError
8
12
  end
9
13
 
10
- # Raised when trying to use a feature in Active Record which requires Active Job but the gem is not present.
11
- class ActiveJobRequiredError < ActiveRecordError
12
- end
13
-
14
14
  # Raised when the single-table inheritance mechanism fails to locate the subclass
15
15
  # (for example due to improper usage of column that
16
16
  # {ActiveRecord::Base.inheritance_column}[rdoc-ref:ModelSchema::ClassMethods#inheritance_column]
@@ -51,10 +51,31 @@ module ActiveRecord
51
51
  class AdapterNotFound < ActiveRecordError
52
52
  end
53
53
 
54
+ # Superclass for all errors raised from an Active Record adapter.
55
+ class AdapterError < ActiveRecordError
56
+ def initialize(message = nil, connection_pool: nil)
57
+ @connection_pool = connection_pool
58
+ super(message)
59
+ end
60
+
61
+ attr_reader :connection_pool
62
+ end
63
+
54
64
  # Raised when connection to the database could not been established (for example when
55
- # {ActiveRecord::Base.connection=}[rdoc-ref:ConnectionHandling#connection]
65
+ # {ActiveRecord::Base.lease_connection=}[rdoc-ref:ConnectionHandling#lease_connection]
56
66
  # is given a +nil+ object).
57
- class ConnectionNotEstablished < ActiveRecordError
67
+ class ConnectionNotEstablished < AdapterError
68
+ def initialize(message = nil, connection_pool: nil)
69
+ super(message, connection_pool: connection_pool)
70
+ end
71
+
72
+ def set_pool(connection_pool)
73
+ unless @connection_pool
74
+ @connection_pool = connection_pool
75
+ end
76
+
77
+ self
78
+ end
58
79
  end
59
80
 
60
81
  # Raised when a connection could not be obtained within the connection
@@ -90,7 +111,7 @@ module ActiveRecord
90
111
  # Raised when a pool was unable to get ahold of all its connections
91
112
  # to perform a "group" action such as
92
113
  # {ActiveRecord::Base.connection_pool.disconnect!}[rdoc-ref:ConnectionAdapters::ConnectionPool#disconnect!]
93
- # or {ActiveRecord::Base.clear_reloadable_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_reloadable_connections!].
114
+ # or {ActiveRecord::Base.connection_handler.clear_reloadable_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_reloadable_connections!].
94
115
  class ExclusiveConnectionTimeoutError < ConnectionTimeoutError
95
116
  end
96
117
 
@@ -112,8 +133,18 @@ module ActiveRecord
112
133
  end
113
134
 
114
135
  # Raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
115
- # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
116
- # methods when a record is invalid and cannot be saved.
136
+ # {ActiveRecord::Base.update_attribute!}[rdoc-ref:Persistence#update_attribute!]
137
+ # methods when a record failed to validate or cannot be saved due to any of the
138
+ # <tt>before_*</tt> callbacks throwing +:abort+. See
139
+ # ActiveRecord::Callbacks for further details.
140
+ #
141
+ # class Product < ActiveRecord::Base
142
+ # before_save do
143
+ # throw :abort if price < 0
144
+ # end
145
+ # end
146
+ #
147
+ # Product.create! # => raises an ActiveRecord::RecordNotSaved
117
148
  class RecordNotSaved < ActiveRecordError
118
149
  attr_reader :record
119
150
 
@@ -124,15 +155,17 @@ module ActiveRecord
124
155
  end
125
156
 
126
157
  # Raised by {ActiveRecord::Base#destroy!}[rdoc-ref:Persistence#destroy!]
127
- # when a call to {#destroy}[rdoc-ref:Persistence#destroy]
128
- # would return false.
158
+ # when a record cannot be destroyed due to any of the
159
+ # <tt>before_destroy</tt> callbacks throwing +:abort+. See
160
+ # ActiveRecord::Callbacks for further details.
129
161
  #
130
- # begin
131
- # complex_operation_that_internally_calls_destroy!
132
- # rescue ActiveRecord::RecordNotDestroyed => invalid
133
- # puts invalid.record.errors
162
+ # class User < ActiveRecord::Base
163
+ # before_destroy do
164
+ # throw :abort if still_active?
165
+ # end
134
166
  # end
135
167
  #
168
+ # User.first.destroy! # => raises an ActiveRecord::RecordNotDestroyed
136
169
  class RecordNotDestroyed < ActiveRecordError
137
170
  attr_reader :record
138
171
 
@@ -155,14 +188,23 @@ module ActiveRecord
155
188
  # Superclass for all database execution errors.
156
189
  #
157
190
  # Wraps the underlying database error as +cause+.
158
- class StatementInvalid < ActiveRecordError
159
- def initialize(message = nil, sql: nil, binds: nil)
160
- super(message || $!&.message)
191
+ class StatementInvalid < AdapterError
192
+ def initialize(message = nil, sql: nil, binds: nil, connection_pool: nil)
193
+ super(message || $!&.message, connection_pool: connection_pool)
161
194
  @sql = sql
162
195
  @binds = binds
163
196
  end
164
197
 
165
198
  attr_reader :sql, :binds
199
+
200
+ def set_query(sql, binds)
201
+ unless @sql
202
+ @sql = sql
203
+ @binds = binds
204
+ end
205
+
206
+ self
207
+ end
166
208
  end
167
209
 
168
210
  # Defunct wrapper class kept for compatibility.
@@ -189,8 +231,13 @@ module ActiveRecord
189
231
  foreign_key: nil,
190
232
  target_table: nil,
191
233
  primary_key: nil,
192
- primary_key_column: nil
234
+ primary_key_column: nil,
235
+ query_parser: nil,
236
+ connection_pool: nil
193
237
  )
238
+ @original_message = message
239
+ @query_parser = query_parser
240
+
194
241
  if table
195
242
  type = primary_key_column.bigint? ? :bigint : primary_key_column.type
196
243
  msg = <<~EOM.squish
@@ -208,7 +255,24 @@ module ActiveRecord
208
255
  if message
209
256
  msg << "\nOriginal message: #{message}"
210
257
  end
211
- super(msg, sql: sql, binds: binds)
258
+
259
+ super(msg, sql: sql, binds: binds, connection_pool: connection_pool)
260
+ end
261
+
262
+ def set_query(sql, binds)
263
+ if @query_parser && !@sql
264
+ self.class.new(
265
+ message: @original_message,
266
+ sql: sql,
267
+ binds: binds,
268
+ connection_pool: @connection_pool,
269
+ **@query_parser.call(sql)
270
+ ).tap do |exception|
271
+ exception.set_backtrace backtrace
272
+ end
273
+ else
274
+ super
275
+ end
212
276
  end
213
277
  end
214
278
 
@@ -224,6 +288,19 @@ module ActiveRecord
224
288
  class RangeError < StatementInvalid
225
289
  end
226
290
 
291
+ # Raised when a statement produces an SQL warning.
292
+ class SQLWarning < AdapterError
293
+ attr_reader :code, :level
294
+ attr_accessor :sql
295
+
296
+ def initialize(message = nil, code = nil, level = nil, sql = nil, connection_pool = nil)
297
+ super(message, connection_pool: connection_pool)
298
+ @code = code
299
+ @level = level
300
+ @sql = sql
301
+ end
302
+ end
303
+
227
304
  # Raised when the number of placeholders in an SQL fragment passed to
228
305
  # {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where]
229
306
  # does not match the number of values supplied.
@@ -242,21 +319,22 @@ module ActiveRecord
242
319
  ActiveRecord::Tasks::DatabaseTasks.create_current
243
320
  end
244
321
 
245
- def initialize(message = nil)
246
- super(message || "Database not found")
322
+ def initialize(message = nil, connection_pool: nil)
323
+ super(message || "Database not found", connection_pool: connection_pool)
247
324
  end
248
325
 
249
326
  class << self
250
327
  def db_error(db_name)
251
328
  NoDatabaseError.new(<<~MSG)
252
- We could not find your database: #{db_name}. Which can be found in the database configuration file located at config/database.yml.
329
+ We could not find your database: #{db_name}. Available database configurations can be found in config/database.yml.
330
+
331
+ To resolve this error:
253
332
 
254
- To resolve this issue:
333
+ - Did you not create the database, or did you delete it? To create the database, run:
255
334
 
256
- - Did you create the database for this app, or delete it? You may need to create your database.
257
- - Has the database name changed? Check your database.yml config has the correct database name.
335
+ bin/rails db:create
258
336
 
259
- To create your database, run:\n\n bin/rails db:create
337
+ - Has the database name changed? Verify that config/database.yml contains the correct database name.
260
338
  MSG
261
339
  end
262
340
  end
@@ -304,6 +382,12 @@ module ActiveRecord
304
382
  end
305
383
 
306
384
  # Raised on attempt to lazily load records that are marked as strict loading.
385
+ #
386
+ # You can resolve this error by eager loading marked records before accessing
387
+ # them. The
388
+ # {Eager Loading Associations}[https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations]
389
+ # guide covers solutions, such as using
390
+ # {ActiveRecord::Base.includes}[rdoc-ref:QueryMethods#includes].
307
391
  class StrictLoadingViolationError < ActiveRecordError
308
392
  end
309
393
 
@@ -396,10 +480,15 @@ module ActiveRecord
396
480
  # relation.loaded? # => true
397
481
  #
398
482
  # # Methods which try to mutate a loaded relation fail.
399
- # relation.where!(title: 'TODO') # => ActiveRecord::ImmutableRelation
400
- # relation.limit!(5) # => ActiveRecord::ImmutableRelation
401
- class ImmutableRelation < ActiveRecordError
483
+ # relation.where!(title: 'TODO') # => ActiveRecord::UnmodifiableRelation
484
+ # relation.limit!(5) # => ActiveRecord::UnmodifiableRelation
485
+ class UnmodifiableRelation < ActiveRecordError
402
486
  end
487
+ deprecate_constant(
488
+ :ImmutableRelation,
489
+ "ActiveRecord::UnmodifiableRelation",
490
+ deprecator: ActiveRecord.deprecator
491
+ )
403
492
 
404
493
  # TransactionIsolationError will be raised under the following conditions:
405
494
  #
@@ -407,13 +496,26 @@ module ActiveRecord
407
496
  # * You are joining an existing open transaction
408
497
  # * You are creating a nested (savepoint) transaction
409
498
  #
410
- # The mysql2 and postgresql adapters support setting the transaction isolation level.
499
+ # The mysql2, trilogy, and postgresql adapters support setting the transaction isolation level.
411
500
  class TransactionIsolationError < ActiveRecordError
412
501
  end
413
502
 
414
503
  # TransactionRollbackError will be raised when a transaction is rolled
415
504
  # back by the database due to a serialization failure or a deadlock.
416
505
  #
506
+ # These exceptions should not be generally rescued in nested transaction
507
+ # blocks, because they have side-effects in the actual enclosing transaction
508
+ # and internal Active Record state. They can be rescued if you are above the
509
+ # root transaction block, though.
510
+ #
511
+ # In that case, beware of transactional tests, however, because they run test
512
+ # cases in their own umbrella transaction. If you absolutely need to handle
513
+ # these exceptions in tests please consider disabling transactional tests in
514
+ # the affected test class (<tt>self.use_transactional_tests = false</tt>).
515
+ #
516
+ # Due to the aforementioned side-effects, this exception should not be raised
517
+ # manually by users.
518
+ #
417
519
  # See the following:
418
520
  #
419
521
  # * https://www.postgresql.org/docs/current/static/transaction-iso.html
@@ -428,11 +530,17 @@ module ActiveRecord
428
530
 
429
531
  # SerializationFailure will be raised when a transaction is rolled
430
532
  # back by the database due to a serialization failure.
533
+ #
534
+ # This is a subclass of TransactionRollbackError, please make sure to check
535
+ # its documentation to be aware of its caveats.
431
536
  class SerializationFailure < TransactionRollbackError
432
537
  end
433
538
 
434
539
  # Deadlocked will be raised when a transaction is rolled
435
540
  # back by the database when a deadlock is encountered.
541
+ #
542
+ # This is a subclass of TransactionRollbackError, please make sure to check
543
+ # its documentation to be aware of its caveats.
436
544
  class Deadlocked < TransactionRollbackError
437
545
  end
438
546
 
@@ -461,6 +569,11 @@ module ActiveRecord
461
569
  class AdapterTimeout < QueryAborted
462
570
  end
463
571
 
572
+ # ConnectionFailed will be raised when the network connection to the
573
+ # database fails while sending a query or waiting for its result.
574
+ class ConnectionFailed < QueryAborted
575
+ end
576
+
464
577
  # UnknownAttributeReference is raised when an unknown and potentially unsafe
465
578
  # value is passed to a query method. For example, passing a non column name
466
579
  # value to a relation's #order method might cause this exception.
@@ -483,4 +596,11 @@ module ActiveRecord
483
596
  # values, such as request parameters or model attributes to query methods.
484
597
  class UnknownAttributeReference < ActiveRecordError
485
598
  end
599
+
600
+ # DatabaseVersionError will be raised when the database version is not supported, or when
601
+ # the database version cannot be determined.
602
+ class DatabaseVersionError < ActiveRecordError
603
+ end
486
604
  end
605
+
606
+ require "active_record/associations/errors"
@@ -16,17 +16,18 @@ module ActiveRecord
16
16
 
17
17
  # Makes the adapter execute EXPLAIN for the tuples of queries and bindings.
18
18
  # Returns a formatted string ready to be logged.
19
- def exec_explain(queries) # :nodoc:
20
- str = queries.map do |sql, binds|
21
- msg = +"EXPLAIN for: #{sql}"
22
- unless binds.empty?
23
- msg << " "
24
- msg << binds.map { |attr| render_bind(attr) }.inspect
25
- end
26
- msg << "\n"
27
- msg << connection.explain(sql, binds)
28
- end.join("\n")
29
-
19
+ def exec_explain(queries, options = []) # :nodoc:
20
+ str = with_connection do |c|
21
+ queries.map do |sql, binds|
22
+ msg = +"#{build_explain_clause(c, options)} #{sql}"
23
+ unless binds.empty?
24
+ msg << " "
25
+ msg << binds.map { |attr| render_bind(c, attr) }.inspect
26
+ end
27
+ msg << "\n"
28
+ msg << c.explain(sql, binds, options)
29
+ end.join("\n")
30
+ end
30
31
  # Overriding inspect to be more human readable, especially in the console.
31
32
  def str.inspect
32
33
  self
@@ -36,7 +37,7 @@ module ActiveRecord
36
37
  end
37
38
 
38
39
  private
39
- def render_bind(attr)
40
+ def render_bind(connection, attr)
40
41
  if ActiveModel::Attribute === attr
41
42
  value = if attr.type.binary? && attr.value
42
43
  "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
@@ -50,5 +51,13 @@ module ActiveRecord
50
51
 
51
52
  [attr&.name, value]
52
53
  end
54
+
55
+ def build_explain_clause(connection, options = [])
56
+ if connection.respond_to?(:build_explain_clause, true)
57
+ connection.build_explain_clause(options)
58
+ else
59
+ "EXPLAIN for:"
60
+ end
61
+ end
53
62
  end
54
63
  end
@@ -12,12 +12,22 @@ module ActiveRecord
12
12
  end
13
13
 
14
14
  def primary_key_type
15
- @primary_key_type ||= @model_class && @model_class.type_for_attribute(@model_class.primary_key).type
15
+ @primary_key_type ||= @model_class && column_type(@model_class.primary_key)
16
16
  end
17
17
 
18
- def has_primary_key_column?
19
- @has_primary_key_column ||= primary_key_name &&
20
- @model_class.columns.any? { |col| col.name == primary_key_name }
18
+ def column_type(column_name)
19
+ @column_type ||= {}
20
+ return @column_type[column_name] if @column_type.key?(column_name)
21
+
22
+ @column_type[column_name] = @model_class && @model_class.type_for_attribute(column_name).type
23
+ end
24
+
25
+ def has_column?(column_name)
26
+ column_names.include?(column_name)
27
+ end
28
+
29
+ def column_names
30
+ @column_names ||= @model_class ? @model_class.columns.map(&:name).to_set : Set.new
21
31
  end
22
32
 
23
33
  def timestamp_column_names
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "base64"
4
+
3
5
  # NOTE: This class has to be defined in compact style in
4
6
  # order for rendering context subclassing to work correctly.
5
7
  class ActiveRecord::FixtureSet::RenderContext # :nodoc:
@@ -87,7 +87,7 @@ module ActiveRecord
87
87
  return unless model_class
88
88
  fill_timestamps
89
89
  interpolate_label
90
- generate_primary_key
90
+ model_class.composite_primary_key? ? generate_composite_primary_key : generate_primary_key
91
91
  resolve_enums
92
92
  resolve_sti_reflections
93
93
  end
@@ -117,14 +117,26 @@ module ActiveRecord
117
117
  end
118
118
 
119
119
  def generate_primary_key
120
- # generate a primary key if necessary
121
- if model_metadata.has_primary_key_column? && !@row.include?(model_metadata.primary_key_name)
122
- @row[model_metadata.primary_key_name] = ActiveRecord::FixtureSet.identify(
123
- @label, model_metadata.primary_key_type
124
- )
120
+ pk = model_metadata.primary_key_name
121
+
122
+ unless column_defined?(pk)
123
+ @row[pk] = ActiveRecord::FixtureSet.identify(@label, model_metadata.column_type(pk))
124
+ end
125
+ end
126
+
127
+ def generate_composite_primary_key
128
+ composite_key = ActiveRecord::FixtureSet.composite_identify(@label, model_metadata.primary_key_name)
129
+ composite_key.each do |column, value|
130
+ next if column_defined?(column)
131
+
132
+ @row[column] = value
125
133
  end
126
134
  end
127
135
 
136
+ def column_defined?(col)
137
+ !model_metadata.has_column?(col) || @row.include?(col)
138
+ end
139
+
128
140
  def resolve_enums
129
141
  reflection_class.defined_enums.each do |name, values|
130
142
  if @row.include?(name)
@@ -151,8 +163,17 @@ module ActiveRecord
151
163
  raise PrimaryKeyError.new(@label, association, value)
152
164
  end
153
165
 
154
- fk_type = reflection_class.type_for_attribute(fk_name).type
155
- @row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
166
+ if fk_name.is_a?(Array)
167
+ composite_key = ActiveRecord::FixtureSet.composite_identify(value, fk_name)
168
+ composite_key.each do |column, value|
169
+ next if column_defined?(column)
170
+
171
+ @row[column] = value
172
+ end
173
+ else
174
+ fk_type = reflection_class.type_for_attribute(fk_name).type
175
+ @row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
176
+ end
156
177
  end
157
178
  when :has_many
158
179
  if association.options[:through]