activerecord 6.0.0 → 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 (376) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +996 -594
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +34 -34
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +22 -20
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +41 -30
  9. data/lib/active_record/associations/association.rb +106 -41
  10. data/lib/active_record/associations/association_scope.rb +30 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +69 -14
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
  13. data/lib/active_record/associations/builder/association.rb +39 -6
  14. data/lib/active_record/associations/builder/belongs_to.rb +47 -17
  15. data/lib/active_record/associations/builder/collection_association.rb +14 -6
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
  17. data/lib/active_record/associations/builder/has_many.rb +7 -3
  18. data/lib/active_record/associations/builder/has_one.rb +13 -16
  19. data/lib/active_record/associations/builder/singular_association.rb +7 -3
  20. data/lib/active_record/associations/collection_association.rb +90 -53
  21. data/lib/active_record/associations/collection_proxy.rb +54 -19
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/errors.rb +265 -0
  24. data/lib/active_record/associations/foreign_association.rb +21 -1
  25. data/lib/active_record/associations/has_many_association.rb +41 -10
  26. data/lib/active_record/associations/has_many_through_association.rb +29 -12
  27. data/lib/active_record/associations/has_one_association.rb +33 -9
  28. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  29. data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
  30. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  31. data/lib/active_record/associations/join_dependency.rb +97 -54
  32. data/lib/active_record/associations/nested_error.rb +47 -0
  33. data/lib/active_record/associations/preloader/association.rb +237 -54
  34. data/lib/active_record/associations/preloader/batch.rb +48 -0
  35. data/lib/active_record/associations/preloader/branch.rb +153 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +51 -17
  37. data/lib/active_record/associations/preloader.rb +55 -121
  38. data/lib/active_record/associations/singular_association.rb +16 -4
  39. data/lib/active_record/associations/through_association.rb +26 -15
  40. data/lib/active_record/associations.rb +454 -440
  41. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  42. data/lib/active_record/attribute_assignment.rb +11 -14
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
  44. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  45. data/lib/active_record/attribute_methods/dirty.rb +75 -34
  46. data/lib/active_record/attribute_methods/primary_key.rb +53 -31
  47. data/lib/active_record/attribute_methods/query.rb +31 -22
  48. data/lib/active_record/attribute_methods/read.rb +16 -17
  49. data/lib/active_record/attribute_methods/serialization.rb +177 -35
  50. data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
  51. data/lib/active_record/attribute_methods/write.rb +16 -28
  52. data/lib/active_record/attribute_methods.rb +227 -100
  53. data/lib/active_record/attributes.rb +94 -56
  54. data/lib/active_record/autosave_association.rb +119 -73
  55. data/lib/active_record/base.rb +31 -21
  56. data/lib/active_record/callbacks.rb +168 -55
  57. data/lib/active_record/coders/column_serializer.rb +61 -0
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +70 -25
  60. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +367 -565
  64. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
  65. data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
  66. data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
  67. data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
  68. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  69. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  70. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
  71. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
  72. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
  73. data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
  74. data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
  75. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
  76. data/lib/active_record/connection_adapters/column.rb +28 -1
  77. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  78. data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
  79. data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
  80. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  81. data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
  82. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
  83. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
  84. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
  85. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
  86. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  87. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  88. data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
  89. data/lib/active_record/connection_adapters/pool_config.rb +83 -0
  90. data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
  91. data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
  92. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
  95. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
  97. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  101. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
  106. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  110. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -4
  111. data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
  121. data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
  123. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  124. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +102 -24
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
  131. data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
  132. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  133. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  134. data/lib/active_record/connection_adapters.rb +176 -0
  135. data/lib/active_record/connection_handling.rb +243 -115
  136. data/lib/active_record/core.rb +481 -199
  137. data/lib/active_record/counter_cache.rb +69 -32
  138. data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
  139. data/lib/active_record/database_configurations/database_config.rb +77 -10
  140. data/lib/active_record/database_configurations/hash_config.rb +148 -26
  141. data/lib/active_record/database_configurations/url_config.rb +44 -45
  142. data/lib/active_record/database_configurations.rb +190 -114
  143. data/lib/active_record/delegated_type.rb +279 -0
  144. data/lib/active_record/deprecator.rb +7 -0
  145. data/lib/active_record/destroy_association_async_job.rb +38 -0
  146. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  147. data/lib/active_record/dynamic_matchers.rb +5 -6
  148. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  149. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  150. data/lib/active_record/encryption/cipher.rb +53 -0
  151. data/lib/active_record/encryption/config.rb +68 -0
  152. data/lib/active_record/encryption/configurable.rb +60 -0
  153. data/lib/active_record/encryption/context.rb +42 -0
  154. data/lib/active_record/encryption/contexts.rb +76 -0
  155. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  156. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  157. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  158. data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
  159. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  160. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  161. data/lib/active_record/encryption/encryptor.rb +171 -0
  162. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  163. data/lib/active_record/encryption/errors.rb +15 -0
  164. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  165. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  166. data/lib/active_record/encryption/key.rb +28 -0
  167. data/lib/active_record/encryption/key_generator.rb +53 -0
  168. data/lib/active_record/encryption/key_provider.rb +46 -0
  169. data/lib/active_record/encryption/message.rb +33 -0
  170. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  171. data/lib/active_record/encryption/message_serializer.rb +96 -0
  172. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  173. data/lib/active_record/encryption/properties.rb +76 -0
  174. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  175. data/lib/active_record/encryption/scheme.rb +100 -0
  176. data/lib/active_record/encryption.rb +58 -0
  177. data/lib/active_record/enum.rb +224 -73
  178. data/lib/active_record/errors.rb +254 -36
  179. data/lib/active_record/explain.rb +30 -17
  180. data/lib/active_record/explain_registry.rb +11 -6
  181. data/lib/active_record/explain_subscriber.rb +2 -2
  182. data/lib/active_record/fixture_set/file.rb +22 -15
  183. data/lib/active_record/fixture_set/model_metadata.rb +15 -6
  184. data/lib/active_record/fixture_set/render_context.rb +3 -1
  185. data/lib/active_record/fixture_set/table_row.rb +88 -16
  186. data/lib/active_record/fixture_set/table_rows.rb +4 -5
  187. data/lib/active_record/fixtures.rb +229 -116
  188. data/lib/active_record/future_result.rb +178 -0
  189. data/lib/active_record/gem_version.rb +4 -4
  190. data/lib/active_record/inheritance.rb +121 -48
  191. data/lib/active_record/insert_all.rb +178 -29
  192. data/lib/active_record/integration.rb +16 -14
  193. data/lib/active_record/internal_metadata.rb +132 -21
  194. data/lib/active_record/legacy_yaml_adapter.rb +3 -36
  195. data/lib/active_record/locking/optimistic.rb +64 -33
  196. data/lib/active_record/locking/pessimistic.rb +21 -8
  197. data/lib/active_record/log_subscriber.rb +61 -30
  198. data/lib/active_record/marshalling.rb +59 -0
  199. data/lib/active_record/message_pack.rb +124 -0
  200. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  201. data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
  202. data/lib/active_record/middleware/database_selector.rb +25 -13
  203. data/lib/active_record/middleware/shard_selector.rb +62 -0
  204. data/lib/active_record/migration/command_recorder.rb +160 -55
  205. data/lib/active_record/migration/compatibility.rb +286 -43
  206. data/lib/active_record/migration/default_strategy.rb +22 -0
  207. data/lib/active_record/migration/execution_strategy.rb +19 -0
  208. data/lib/active_record/migration/join_table.rb +1 -2
  209. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  210. data/lib/active_record/migration.rb +421 -193
  211. data/lib/active_record/model_schema.rb +217 -125
  212. data/lib/active_record/nested_attributes.rb +62 -27
  213. data/lib/active_record/no_touching.rb +4 -4
  214. data/lib/active_record/normalization.rb +163 -0
  215. data/lib/active_record/persistence.rb +322 -319
  216. data/lib/active_record/promise.rb +84 -0
  217. data/lib/active_record/query_cache.rb +18 -15
  218. data/lib/active_record/query_logs.rb +193 -0
  219. data/lib/active_record/query_logs_formatter.rb +41 -0
  220. data/lib/active_record/querying.rb +54 -14
  221. data/lib/active_record/railtie.rb +250 -72
  222. data/lib/active_record/railties/console_sandbox.rb +2 -4
  223. data/lib/active_record/railties/controller_runtime.rb +25 -11
  224. data/lib/active_record/railties/databases.rake +312 -197
  225. data/lib/active_record/railties/job_runtime.rb +23 -0
  226. data/lib/active_record/readonly_attributes.rb +45 -3
  227. data/lib/active_record/reflection.rb +389 -146
  228. data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
  229. data/lib/active_record/relation/batches.rb +214 -73
  230. data/lib/active_record/relation/calculations.rb +379 -124
  231. data/lib/active_record/relation/delegation.rb +36 -23
  232. data/lib/active_record/relation/finder_methods.rb +159 -49
  233. data/lib/active_record/relation/from_clause.rb +5 -1
  234. data/lib/active_record/relation/merger.rb +41 -33
  235. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
  236. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
  237. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
  238. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  239. data/lib/active_record/relation/predicate_builder.rb +79 -53
  240. data/lib/active_record/relation/query_attribute.rb +30 -12
  241. data/lib/active_record/relation/query_methods.rb +1156 -279
  242. data/lib/active_record/relation/record_fetch_warning.rb +12 -11
  243. data/lib/active_record/relation/spawn_methods.rb +10 -9
  244. data/lib/active_record/relation/where_clause.rb +100 -66
  245. data/lib/active_record/relation.rb +829 -194
  246. data/lib/active_record/result.rb +76 -56
  247. data/lib/active_record/runtime_registry.rb +71 -13
  248. data/lib/active_record/sanitization.rb +86 -47
  249. data/lib/active_record/schema.rb +39 -23
  250. data/lib/active_record/schema_dumper.rb +140 -33
  251. data/lib/active_record/schema_migration.rb +74 -29
  252. data/lib/active_record/scoping/default.rb +73 -19
  253. data/lib/active_record/scoping/named.rb +10 -28
  254. data/lib/active_record/scoping.rb +65 -35
  255. data/lib/active_record/secure_password.rb +60 -0
  256. data/lib/active_record/secure_token.rb +34 -8
  257. data/lib/active_record/serialization.rb +11 -4
  258. data/lib/active_record/signed_id.rb +138 -0
  259. data/lib/active_record/statement_cache.rb +26 -10
  260. data/lib/active_record/store.rb +19 -14
  261. data/lib/active_record/suppressor.rb +15 -17
  262. data/lib/active_record/table_metadata.rb +46 -36
  263. data/lib/active_record/tasks/database_tasks.rb +371 -205
  264. data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
  265. data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
  266. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
  267. data/lib/active_record/test_databases.rb +5 -4
  268. data/lib/active_record/test_fixtures.rb +189 -104
  269. data/lib/active_record/testing/query_assertions.rb +121 -0
  270. data/lib/active_record/timestamp.rb +35 -25
  271. data/lib/active_record/token_for.rb +123 -0
  272. data/lib/active_record/touch_later.rb +31 -27
  273. data/lib/active_record/transaction.rb +132 -0
  274. data/lib/active_record/transactions.rb +131 -99
  275. data/lib/active_record/translation.rb +3 -5
  276. data/lib/active_record/type/adapter_specific_registry.rb +33 -18
  277. data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
  278. data/lib/active_record/type/internal/timezone.rb +7 -2
  279. data/lib/active_record/type/serialized.rb +11 -6
  280. data/lib/active_record/type/time.rb +14 -0
  281. data/lib/active_record/type/type_map.rb +17 -21
  282. data/lib/active_record/type/unsigned_integer.rb +0 -1
  283. data/lib/active_record/type.rb +7 -2
  284. data/lib/active_record/type_caster/connection.rb +4 -5
  285. data/lib/active_record/type_caster/map.rb +8 -5
  286. data/lib/active_record/validations/absence.rb +1 -1
  287. data/lib/active_record/validations/associated.rb +13 -8
  288. data/lib/active_record/validations/numericality.rb +36 -0
  289. data/lib/active_record/validations/presence.rb +5 -28
  290. data/lib/active_record/validations/uniqueness.rb +88 -18
  291. data/lib/active_record/validations.rb +15 -8
  292. data/lib/active_record/version.rb +1 -1
  293. data/lib/active_record.rb +446 -40
  294. data/lib/arel/alias_predication.rb +1 -1
  295. data/lib/arel/attributes/attribute.rb +4 -8
  296. data/lib/arel/collectors/bind.rb +8 -1
  297. data/lib/arel/collectors/composite.rb +15 -0
  298. data/lib/arel/collectors/sql_string.rb +7 -0
  299. data/lib/arel/collectors/substitute_binds.rb +7 -0
  300. data/lib/arel/crud.rb +30 -22
  301. data/lib/arel/delete_manager.rb +23 -4
  302. data/lib/arel/errors.rb +10 -0
  303. data/lib/arel/factory_methods.rb +4 -0
  304. data/lib/arel/filter_predications.rb +9 -0
  305. data/lib/arel/insert_manager.rb +2 -3
  306. data/lib/arel/nodes/binary.rb +82 -9
  307. data/lib/arel/nodes/bind_param.rb +8 -0
  308. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  309. data/lib/arel/nodes/casted.rb +22 -10
  310. data/lib/arel/nodes/cte.rb +36 -0
  311. data/lib/arel/nodes/delete_statement.rb +14 -13
  312. data/lib/arel/nodes/equality.rb +6 -9
  313. data/lib/arel/nodes/filter.rb +10 -0
  314. data/lib/arel/nodes/fragments.rb +35 -0
  315. data/lib/arel/nodes/function.rb +1 -0
  316. data/lib/arel/nodes/grouping.rb +3 -0
  317. data/lib/arel/nodes/homogeneous_in.rb +68 -0
  318. data/lib/arel/nodes/in.rb +8 -1
  319. data/lib/arel/nodes/infix_operation.rb +13 -1
  320. data/lib/arel/nodes/insert_statement.rb +2 -2
  321. data/lib/arel/nodes/join_source.rb +1 -1
  322. data/lib/arel/nodes/leading_join.rb +8 -0
  323. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  324. data/lib/arel/nodes/node.rb +122 -11
  325. data/lib/arel/nodes/ordering.rb +27 -0
  326. data/lib/arel/nodes/select_core.rb +2 -2
  327. data/lib/arel/nodes/select_statement.rb +2 -2
  328. data/lib/arel/nodes/sql_literal.rb +16 -0
  329. data/lib/arel/nodes/table_alias.rb +11 -3
  330. data/lib/arel/nodes/unary.rb +0 -1
  331. data/lib/arel/nodes/update_statement.rb +11 -4
  332. data/lib/arel/nodes.rb +10 -3
  333. data/lib/arel/predications.rb +31 -28
  334. data/lib/arel/select_manager.rb +18 -9
  335. data/lib/arel/table.rb +21 -10
  336. data/lib/arel/tree_manager.rb +8 -15
  337. data/lib/arel/update_manager.rb +25 -5
  338. data/lib/arel/visitors/dot.rb +94 -90
  339. data/lib/arel/visitors/mysql.rb +34 -6
  340. data/lib/arel/visitors/postgresql.rb +5 -16
  341. data/lib/arel/visitors/sqlite.rb +25 -1
  342. data/lib/arel/visitors/to_sql.rb +227 -81
  343. data/lib/arel/visitors/visitor.rb +2 -3
  344. data/lib/arel/visitors.rb +0 -7
  345. data/lib/arel.rb +37 -15
  346. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  347. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  348. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  349. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  350. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
  351. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  352. data/lib/rails/generators/active_record/migration.rb +9 -3
  353. data/lib/rails/generators/active_record/model/USAGE +113 -0
  354. data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
  355. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  356. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  357. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  358. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  359. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  360. metadata +117 -30
  361. data/lib/active_record/attribute_decorators.rb +0 -90
  362. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  363. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  364. data/lib/active_record/define_callbacks.rb +0 -22
  365. data/lib/active_record/null_relation.rb +0 -68
  366. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  367. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  368. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  369. data/lib/arel/attributes.rb +0 -22
  370. data/lib/arel/visitors/depth_first.rb +0 -204
  371. data/lib/arel/visitors/ibm_db.rb +0 -34
  372. data/lib/arel/visitors/informix.rb +0 -62
  373. data/lib/arel/visitors/mssql.rb +0 -157
  374. data/lib/arel/visitors/oracle.rb +0 -159
  375. data/lib/arel/visitors/oracle12.rb +0 -66
  376. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class FutureResult # :nodoc:
5
+ class Complete
6
+ attr_reader :result
7
+ delegate :empty?, :to_a, to: :result
8
+
9
+ def initialize(result)
10
+ @result = result
11
+ end
12
+
13
+ def pending?
14
+ false
15
+ end
16
+
17
+ def canceled?
18
+ false
19
+ end
20
+
21
+ def then(&block)
22
+ Promise::Complete.new(@result.then(&block))
23
+ end
24
+ end
25
+
26
+ class EventBuffer
27
+ def initialize(future_result, instrumenter)
28
+ @future_result = future_result
29
+ @instrumenter = instrumenter
30
+ @events = []
31
+ end
32
+
33
+ def instrument(name, payload = {}, &block)
34
+ event = @instrumenter.new_event(name, payload)
35
+ begin
36
+ event.record(&block)
37
+ ensure
38
+ @events << event
39
+ end
40
+ end
41
+
42
+ def flush
43
+ events, @events = @events, []
44
+ events.each do |event|
45
+ event.payload[:lock_wait] = @future_result.lock_wait
46
+ ActiveSupport::Notifications.publish_event(event)
47
+ end
48
+ end
49
+ end
50
+
51
+ Canceled = Class.new(ActiveRecordError)
52
+
53
+ def self.wrap(result)
54
+ case result
55
+ when self, Complete
56
+ result
57
+ else
58
+ Complete.new(result)
59
+ end
60
+ end
61
+
62
+ delegate :empty?, :to_a, to: :result
63
+
64
+ attr_reader :lock_wait
65
+
66
+ def initialize(pool, *args, **kwargs)
67
+ @mutex = Mutex.new
68
+
69
+ @session = nil
70
+ @pool = pool
71
+ @args = args
72
+ @kwargs = kwargs
73
+
74
+ @pending = true
75
+ @error = nil
76
+ @result = nil
77
+ @instrumenter = ActiveSupport::Notifications.instrumenter
78
+ @event_buffer = nil
79
+ end
80
+
81
+ def then(&block)
82
+ Promise.new(self, block)
83
+ end
84
+
85
+ def schedule!(session)
86
+ @session = session
87
+ @pool.schedule_query(self)
88
+ end
89
+
90
+ def execute!(connection)
91
+ execute_query(connection)
92
+ end
93
+
94
+ def cancel
95
+ @pending = false
96
+ @error = Canceled
97
+ self
98
+ end
99
+
100
+ def execute_or_skip
101
+ return unless pending?
102
+
103
+ @pool.with_connection do |connection|
104
+ return unless @mutex.try_lock
105
+ begin
106
+ if pending?
107
+ @event_buffer = EventBuffer.new(self, @instrumenter)
108
+ connection.with_instrumenter(@event_buffer) do
109
+ execute_query(connection, async: true)
110
+ end
111
+ end
112
+ ensure
113
+ @mutex.unlock
114
+ end
115
+ end
116
+ end
117
+
118
+ def result
119
+ execute_or_wait
120
+ @event_buffer&.flush
121
+
122
+ if canceled?
123
+ raise Canceled
124
+ elsif @error
125
+ raise @error
126
+ else
127
+ @result
128
+ end
129
+ end
130
+
131
+ def pending?
132
+ @pending && (!@session || @session.active?)
133
+ end
134
+
135
+ def canceled?
136
+ @session && !@session.active?
137
+ end
138
+
139
+ private
140
+ def execute_or_wait
141
+ if pending?
142
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
143
+ @mutex.synchronize do
144
+ if pending?
145
+ @pool.with_connection do |connection|
146
+ execute_query(connection)
147
+ end
148
+ else
149
+ @lock_wait = (Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) - start)
150
+ end
151
+ end
152
+ else
153
+ @lock_wait = 0.0
154
+ end
155
+ end
156
+
157
+ def execute_query(connection, async: false)
158
+ @result = exec_query(connection, *@args, **@kwargs, async: async)
159
+ rescue => error
160
+ @error = error
161
+ ensure
162
+ @pending = false
163
+ end
164
+
165
+ def exec_query(connection, *args, **kwargs)
166
+ connection.internal_exec_query(*args, **kwargs)
167
+ end
168
+
169
+ class SelectAll < FutureResult # :nodoc:
170
+ private
171
+ def exec_query(*, **)
172
+ super
173
+ rescue ::RangeError
174
+ ActiveRecord::Result.empty
175
+ end
176
+ end
177
+ end
178
+ end
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
- # Returns the version of the currently loaded Active Record as a <tt>Gem::Version</tt>
4
+ # Returns the currently loaded version of Active Record as a +Gem::Version+.
5
5
  def self.gem_version
6
6
  Gem::Version.new VERSION::STRING
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 6
11
- MINOR = 0
12
- TINY = 0
10
+ MAJOR = 7
11
+ MINOR = 2
12
+ TINY = 3
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/inflector"
3
4
  require "active_support/core_ext/hash/indifferent_access"
4
5
 
5
6
  module ActiveRecord
6
- # == Single table inheritance
7
+ # = Single table inheritance
7
8
  #
8
9
  # Active Record allows inheritance by storing the name of the class in a column that by
9
10
  # default is named "type" (can be changed by overwriting <tt>Base.inheritance_column</tt>).
@@ -31,16 +32,21 @@ module ActiveRecord
31
32
  # be triggered. In that case, it'll work just like normal subclasses with no special magic
32
33
  # for differentiating between them or reloading the right type with find.
33
34
  #
34
- # Note, all the attributes for all the cases are kept in the same table. Read more:
35
- # https://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
35
+ # Note, all the attributes for all the cases are kept in the same table.
36
+ # Read more:
37
+ # * https://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
36
38
  #
37
39
  module Inheritance
38
40
  extend ActiveSupport::Concern
39
41
 
40
42
  included do
43
+ class_attribute :store_full_class_name, instance_writer: false, default: true
44
+
41
45
  # Determines whether to store the full constant name including namespace when using STI.
42
46
  # This is true, by default.
43
47
  class_attribute :store_full_sti_class, instance_writer: false, default: true
48
+
49
+ set_base_class
44
50
  end
45
51
 
46
52
  module ClassMethods
@@ -52,7 +58,7 @@ module ActiveRecord
52
58
  raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
53
59
  end
54
60
 
55
- if has_attribute?(inheritance_column)
61
+ if _has_attribute?(inheritance_column)
56
62
  subclass = subclass_from_attributes(attributes)
57
63
 
58
64
  if subclass.nil? && scope_attributes = current_scope&.scope_for_create
@@ -83,30 +89,30 @@ module ActiveRecord
83
89
  end
84
90
  end
85
91
 
86
- def finder_needs_type_condition? #:nodoc:
92
+ def finder_needs_type_condition? # :nodoc:
87
93
  # This is like this because benchmarking justifies the strange :false stuff
88
94
  :true == (@finder_needs_type_condition ||= descends_from_active_record? ? :false : :true)
89
95
  end
90
96
 
91
- # Returns the class descending directly from ActiveRecord::Base, or
92
- # an abstract class, if any, in the inheritance hierarchy.
97
+ # Returns the first class in the inheritance hierarchy that descends from either an
98
+ # abstract class or from <tt>ActiveRecord::Base</tt>.
93
99
  #
94
- # If A extends ActiveRecord::Base, A.base_class will return A. If B descends from A
95
- # through some arbitrarily deep hierarchy, B.base_class will return A.
100
+ # Consider the following behaviour:
96
101
  #
97
- # If B < A and C < B and if A is an abstract_class then both B.base_class
98
- # and C.base_class would return B as the answer since A is an abstract_class.
99
- def base_class
100
- unless self < Base
101
- raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
102
- end
103
-
104
- if superclass == Base || superclass.abstract_class?
105
- self
106
- else
107
- superclass.base_class
108
- end
109
- end
102
+ # class ApplicationRecord < ActiveRecord::Base
103
+ # self.abstract_class = true
104
+ # end
105
+ # class Shape < ApplicationRecord
106
+ # self.abstract_class = true
107
+ # end
108
+ # Polygon = Class.new(Shape)
109
+ # Square = Class.new(Polygon)
110
+ #
111
+ # ApplicationRecord.base_class # => ApplicationRecord
112
+ # Shape.base_class # => Shape
113
+ # Polygon.base_class # => Polygon
114
+ # Square.base_class # => Polygon
115
+ attr_reader :base_class
110
116
 
111
117
  # Returns whether the class is a base class.
112
118
  # See #base_class for more information.
@@ -121,7 +127,7 @@ module ActiveRecord
121
127
  # true.
122
128
  # +ApplicationRecord+, for example, is generated as an abstract class.
123
129
  #
124
- # Consider the following default behaviour:
130
+ # Consider the following default behavior:
125
131
  #
126
132
  # Shape = Class.new(ActiveRecord::Base)
127
133
  # Polygon = Class.new(Shape)
@@ -159,34 +165,88 @@ module ActiveRecord
159
165
 
160
166
  # Returns whether this class is an abstract class or not.
161
167
  def abstract_class?
162
- defined?(@abstract_class) && @abstract_class == true
168
+ @abstract_class == true
169
+ end
170
+
171
+ # Sets the application record class for Active Record
172
+ #
173
+ # This is useful if your application uses a different class than
174
+ # ApplicationRecord for your primary abstract class. This class
175
+ # will share a database connection with Active Record. It is the class
176
+ # that connects to your primary database.
177
+ def primary_abstract_class
178
+ if ActiveRecord.application_record_class && ActiveRecord.application_record_class.name != name
179
+ raise ArgumentError, "The `primary_abstract_class` is already set to #{ActiveRecord.application_record_class.inspect}. There can only be one `primary_abstract_class` in an application."
180
+ end
181
+
182
+ self.abstract_class = true
183
+ ActiveRecord.application_record_class = self
163
184
  end
164
185
 
186
+ # Returns the value to be stored in the inheritance column for STI.
165
187
  def sti_name
166
- store_full_sti_class ? name : name.demodulize
188
+ store_full_sti_class && store_full_class_name ? name : name.demodulize
167
189
  end
168
190
 
191
+ # Returns the class for the provided +type_name+.
192
+ #
193
+ # It is used to find the class correspondent to the value stored in the inheritance column.
194
+ def sti_class_for(type_name)
195
+ if store_full_sti_class && store_full_class_name
196
+ type_name.constantize
197
+ else
198
+ compute_type(type_name)
199
+ end
200
+ rescue NameError
201
+ raise SubclassNotFound,
202
+ "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
203
+ "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
204
+ "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
205
+ "or overwrite #{name}.inheritance_column to use another column for that information. " \
206
+ "If you wish to disable single-table inheritance for #{name} set " \
207
+ "#{name}.inheritance_column to nil"
208
+ end
209
+
210
+ # Returns the value to be stored in the polymorphic type column for Polymorphic Associations.
169
211
  def polymorphic_name
170
- base_class.name
212
+ store_full_class_name ? base_class.name : base_class.name.demodulize
171
213
  end
172
214
 
173
- def inherited(subclass)
174
- subclass.instance_variable_set(:@_type_candidates_cache, Concurrent::Map.new)
215
+ # Returns the class for the provided +name+.
216
+ #
217
+ # It is used to find the class correspondent to the value stored in the polymorphic type column.
218
+ def polymorphic_class_for(name)
219
+ if store_full_class_name
220
+ name.constantize
221
+ else
222
+ compute_type(name)
223
+ end
224
+ end
225
+
226
+ def dup # :nodoc:
227
+ # `initialize_dup` / `initialize_copy` don't work when defined
228
+ # in the `singleton_class`.
229
+ other = super
230
+ other.set_base_class
231
+ other
232
+ end
233
+
234
+ def initialize_clone(other) # :nodoc:
175
235
  super
236
+ set_base_class
176
237
  end
177
238
 
178
239
  protected
179
-
180
240
  # Returns the class type of the record using the current module as a prefix. So descendants of
181
241
  # MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.
182
242
  def compute_type(type_name)
183
243
  if type_name.start_with?("::")
184
244
  # If the type is prefixed with a scope operator then we assume that
185
245
  # the type_name is an absolute reference.
186
- ActiveSupport::Dependencies.constantize(type_name)
246
+ type_name.constantize
187
247
  else
188
248
  type_candidate = @_type_candidates_cache[type_name]
189
- if type_candidate && type_constant = ActiveSupport::Dependencies.safe_constantize(type_candidate)
249
+ if type_candidate && type_constant = type_candidate.safe_constantize
190
250
  return type_constant
191
251
  end
192
252
 
@@ -196,7 +256,7 @@ module ActiveRecord
196
256
  candidates << type_name
197
257
 
198
258
  candidates.each do |candidate|
199
- constant = ActiveSupport::Dependencies.safe_constantize(candidate)
259
+ constant = candidate.safe_constantize
200
260
  if candidate == constant.to_s
201
261
  @_type_candidates_cache[type_name] = candidate
202
262
  return constant
@@ -207,7 +267,31 @@ module ActiveRecord
207
267
  end
208
268
  end
209
269
 
270
+ def set_base_class # :nodoc:
271
+ @base_class = if self == Base
272
+ self
273
+ else
274
+ unless self < Base
275
+ raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
276
+ end
277
+
278
+ if superclass == Base || superclass.abstract_class?
279
+ self
280
+ else
281
+ superclass.base_class
282
+ end
283
+ end
284
+ end
285
+
210
286
  private
287
+ def inherited(subclass)
288
+ super
289
+ subclass.set_base_class
290
+ subclass.instance_variable_set(:@_type_candidates_cache, Concurrent::Map.new)
291
+ subclass.class_eval do
292
+ @finder_needs_type_condition = nil
293
+ end
294
+ end
211
295
 
212
296
  # Called by +instantiate+ to decide which class to use for a new
213
297
  # record instance. For single-table inheritance, we check the record
@@ -221,32 +305,22 @@ module ActiveRecord
221
305
  end
222
306
 
223
307
  def using_single_table_inheritance?(record)
224
- record[inheritance_column].present? && has_attribute?(inheritance_column)
308
+ record[inheritance_column].present? && _has_attribute?(inheritance_column)
225
309
  end
226
310
 
227
311
  def find_sti_class(type_name)
228
312
  type_name = base_class.type_for_attribute(inheritance_column).cast(type_name)
229
- subclass = begin
230
- if store_full_sti_class
231
- ActiveSupport::Dependencies.constantize(type_name)
232
- else
233
- compute_type(type_name)
234
- end
235
- rescue NameError
236
- raise SubclassNotFound,
237
- "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
238
- "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
239
- "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
240
- "or overwrite #{name}.inheritance_column to use another column for that information."
241
- end
313
+ subclass = sti_class_for(type_name)
314
+
242
315
  unless subclass == self || descendants.include?(subclass)
243
316
  raise SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}"
244
317
  end
318
+
245
319
  subclass
246
320
  end
247
321
 
248
322
  def type_condition(table = arel_table)
249
- sti_column = arel_attribute(inheritance_column, table)
323
+ sti_column = table[inheritance_column]
250
324
  sti_names = ([self] + descendants).map(&:sti_name)
251
325
 
252
326
  predicate_builder.build(sti_column, sti_names)
@@ -272,7 +346,6 @@ module ActiveRecord
272
346
  end
273
347
 
274
348
  private
275
-
276
349
  def initialize_internals_callback
277
350
  super
278
351
  ensure_proper_type