activerecord 4.2.0 → 6.1.7.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 (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1221 -796
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +267 -249
  8. data/lib/active_record/association_relation.rb +45 -7
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +172 -67
  11. data/lib/active_record/associations/association_scope.rb +105 -129
  12. data/lib/active_record/associations/belongs_to_association.rb +85 -59
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -33
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +168 -279
  22. data/lib/active_record/associations/collection_proxy.rb +263 -155
  23. data/lib/active_record/associations/foreign_association.rb +33 -0
  24. data/lib/active_record/associations/has_many_association.rb +57 -84
  25. data/lib/active_record/associations/has_many_through_association.rb +70 -82
  26. data/lib/active_record/associations/has_one_association.rb +74 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +175 -164
  32. data/lib/active_record/associations/preloader/association.rb +107 -112
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +99 -96
  35. data/lib/active_record/associations/singular_association.rb +18 -45
  36. data/lib/active_record/associations/through_association.rb +49 -24
  37. data/lib/active_record/associations.rb +1845 -1597
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -138
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
  46. data/lib/active_record/attribute_methods/write.rb +25 -56
  47. data/lib/active_record/attribute_methods.rb +153 -162
  48. data/lib/active_record/attributes.rb +234 -70
  49. data/lib/active_record/autosave_association.rb +157 -69
  50. data/lib/active_record/base.rb +49 -50
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +46 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
  119. data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +488 -243
  133. data/lib/active_record/counter_cache.rb +71 -50
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +273 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +212 -94
  143. data/lib/active_record/errors.rb +225 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +11 -6
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +273 -496
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +64 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +52 -0
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +103 -95
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +298 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +685 -309
  170. data/lib/active_record/model_schema.rb +420 -113
  171. data/lib/active_record/nested_attributes.rb +265 -216
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +574 -135
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +175 -54
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +533 -216
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +485 -310
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +326 -244
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +318 -256
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +99 -84
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +139 -96
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -409
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +23 -21
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -342
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -26
  209. data/lib/active_record/scoping/default.rb +96 -82
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +133 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +366 -129
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +291 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +181 -152
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -41
  231. data/lib/active_record/type/date_time.rb +4 -38
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +33 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +65 -48
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +44 -28
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +175 -65
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  347. data/lib/active_record/attribute.rb +0 -149
  348. data/lib/active_record/attribute_decorators.rb +0 -66
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  352. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  353. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  354. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  355. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  356. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  357. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  358. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  359. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  360. data/lib/active_record/type/big_integer.rb +0 -13
  361. data/lib/active_record/type/binary.rb +0 -50
  362. data/lib/active_record/type/boolean.rb +0 -30
  363. data/lib/active_record/type/decimal.rb +0 -40
  364. data/lib/active_record/type/decorator.rb +0 -14
  365. data/lib/active_record/type/float.rb +0 -19
  366. data/lib/active_record/type/integer.rb +0 -55
  367. data/lib/active_record/type/mutable.rb +0 -16
  368. data/lib/active_record/type/numeric.rb +0 -36
  369. data/lib/active_record/type/string.rb +0 -36
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -101
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  374. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,13 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  class TransactionState
4
- attr_reader :parent
5
-
6
- VALID_STATES = Set.new([:committed, :rolledback, nil])
7
-
8
6
  def initialize(state = nil)
9
7
  @state = state
10
- @parent = nil
8
+ @children = nil
9
+ end
10
+
11
+ def add_child(state)
12
+ @children ||= []
13
+ @children << state
11
14
  end
12
15
 
13
16
  def finalized?
@@ -15,91 +18,148 @@ module ActiveRecord
15
18
  end
16
19
 
17
20
  def committed?
18
- @state == :committed
21
+ @state == :committed || @state == :fully_committed
22
+ end
23
+
24
+ def fully_committed?
25
+ @state == :fully_committed
19
26
  end
20
27
 
21
28
  def rolledback?
22
- @state == :rolledback
29
+ @state == :rolledback || @state == :fully_rolledback
30
+ end
31
+
32
+ def fully_rolledback?
33
+ @state == :fully_rolledback
34
+ end
35
+
36
+ def invalidated?
37
+ @state == :invalidated
38
+ end
39
+
40
+ def fully_completed?
41
+ completed?
23
42
  end
24
43
 
25
44
  def completed?
26
45
  committed? || rolledback?
27
46
  end
28
47
 
29
- def set_state(state)
30
- if !VALID_STATES.include?(state)
31
- raise ArgumentError, "Invalid transaction state: #{state}"
32
- end
33
- @state = state
48
+ def rollback!
49
+ @children&.each { |c| c.rollback! }
50
+ @state = :rolledback
51
+ end
52
+
53
+ def full_rollback!
54
+ @children&.each { |c| c.rollback! }
55
+ @state = :fully_rolledback
56
+ end
57
+
58
+ def invalidate!
59
+ @children&.each { |c| c.invalidate! }
60
+ @state = :invalidated
61
+ end
62
+
63
+ def commit!
64
+ @state = :committed
65
+ end
66
+
67
+ def full_commit!
68
+ @state = :fully_committed
69
+ end
70
+
71
+ def nullify!
72
+ @state = nil
34
73
  end
35
74
  end
36
75
 
37
76
  class NullTransaction #:nodoc:
38
77
  def initialize; end
78
+ def state; end
39
79
  def closed?; true; end
40
80
  def open?; false; end
41
81
  def joinable?; false; end
42
- def add_record(record); end
82
+ def add_record(record, _ = true); end
43
83
  end
44
84
 
45
85
  class Transaction #:nodoc:
86
+ attr_reader :connection, :state, :savepoint_name, :isolation_level
87
+ attr_accessor :written
46
88
 
47
- attr_reader :connection, :state, :records, :savepoint_name
48
- attr_writer :joinable
49
-
50
- def initialize(connection, options)
89
+ def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false)
51
90
  @connection = connection
52
91
  @state = TransactionState.new
53
- @records = []
54
- @joinable = options.fetch(:joinable, true)
92
+ @records = nil
93
+ @isolation_level = isolation
94
+ @materialized = false
95
+ @joinable = joinable
96
+ @run_commit_callbacks = run_commit_callbacks
97
+ @lazy_enrollment_records = nil
55
98
  end
56
99
 
57
- def add_record(record)
58
- if record.has_transactional_callbacks?
59
- records << record
100
+ def add_record(record, ensure_finalize = true)
101
+ @records ||= []
102
+ if ensure_finalize
103
+ @records << record
60
104
  else
61
- record.set_transaction_state(@state)
105
+ @lazy_enrollment_records ||= ObjectSpace::WeakMap.new
106
+ @lazy_enrollment_records[record] = record
62
107
  end
63
108
  end
64
109
 
65
- def rollback
66
- @state.set_state(:rolledback)
110
+ def records
111
+ if @lazy_enrollment_records
112
+ @records.concat @lazy_enrollment_records.values
113
+ @lazy_enrollment_records = nil
114
+ end
115
+ @records
116
+ end
117
+
118
+ def materialize!
119
+ @materialized = true
120
+ end
121
+
122
+ def materialized?
123
+ @materialized
67
124
  end
68
125
 
69
126
  def rollback_records
70
- ite = records.uniq
127
+ return unless records
128
+ ite = records.uniq(&:__id__)
129
+ already_run_callbacks = {}
71
130
  while record = ite.shift
72
- begin
73
- record.rolledback! full_rollback?
74
- rescue => e
75
- raise if ActiveRecord::Base.raise_in_transactional_callbacks
76
- record.logger.error(e) if record.respond_to?(:logger) && record.logger
77
- end
131
+ trigger_callbacks = record.trigger_transactional_callbacks?
132
+ should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
133
+ already_run_callbacks[record] ||= trigger_callbacks
134
+ record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
78
135
  end
79
136
  ensure
80
- ite.each do |i|
81
- i.rolledback!(full_rollback?, false)
137
+ ite&.each do |i|
138
+ i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
82
139
  end
83
140
  end
84
141
 
85
- def commit
86
- @state.set_state(:committed)
142
+ def before_commit_records
143
+ records.uniq.each(&:before_committed!) if records && @run_commit_callbacks
87
144
  end
88
145
 
89
146
  def commit_records
90
- ite = records.uniq
147
+ return unless records
148
+ ite = records.uniq(&:__id__)
149
+ already_run_callbacks = {}
91
150
  while record = ite.shift
92
- begin
93
- record.committed!
94
- rescue => e
95
- raise if ActiveRecord::Base.raise_in_transactional_callbacks
96
- record.logger.error(e) if record.respond_to?(:logger) && record.logger
151
+ if @run_commit_callbacks
152
+ trigger_callbacks = record.trigger_transactional_callbacks?
153
+ should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
154
+ already_run_callbacks[record] ||= trigger_callbacks
155
+ record.committed!(should_run_callbacks: should_run_callbacks)
156
+ else
157
+ # if not running callbacks, only adds the record to the parent transaction
158
+ connection.add_transaction_record(record)
97
159
  end
98
160
  end
99
161
  ensure
100
- ite.each do |i|
101
- i.committed!(false)
102
- end
162
+ ite&.each { |i| i.committed!(should_run_callbacks: false) }
103
163
  end
104
164
 
105
165
  def full_rollback?; true; end
@@ -109,52 +169,55 @@ module ActiveRecord
109
169
  end
110
170
 
111
171
  class SavepointTransaction < Transaction
172
+ def initialize(connection, savepoint_name, parent_transaction, **options)
173
+ super(connection, **options)
174
+
175
+ parent_transaction.state.add_child(@state)
112
176
 
113
- def initialize(connection, savepoint_name, options)
114
- super(connection, options)
115
- if options[:isolation]
177
+ if isolation_level
116
178
  raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
117
179
  end
118
- connection.create_savepoint(@savepoint_name = savepoint_name)
180
+
181
+ @savepoint_name = savepoint_name
119
182
  end
120
183
 
121
- def rollback
122
- connection.rollback_to_savepoint(savepoint_name)
184
+ def materialize!
185
+ connection.create_savepoint(savepoint_name)
123
186
  super
124
- rollback_records
187
+ end
188
+
189
+ def rollback
190
+ connection.rollback_to_savepoint(savepoint_name) if materialized?
191
+ @state.rollback!
125
192
  end
126
193
 
127
194
  def commit
128
- connection.release_savepoint(savepoint_name)
129
- super
130
- parent = connection.transaction_manager.current_transaction
131
- records.each { |r| parent.add_record(r) }
195
+ connection.release_savepoint(savepoint_name) if materialized?
196
+ @state.commit!
132
197
  end
133
198
 
134
199
  def full_rollback?; false; end
135
200
  end
136
201
 
137
202
  class RealTransaction < Transaction
138
-
139
- def initialize(connection, options)
140
- super
141
- if options[:isolation]
142
- connection.begin_isolated_db_transaction(options[:isolation])
203
+ def materialize!
204
+ if isolation_level
205
+ connection.begin_isolated_db_transaction(isolation_level)
143
206
  else
144
207
  connection.begin_db_transaction
145
208
  end
209
+
210
+ super
146
211
  end
147
212
 
148
213
  def rollback
149
- connection.rollback_db_transaction
150
- super
151
- rollback_records
214
+ connection.rollback_db_transaction if materialized?
215
+ @state.full_rollback!
152
216
  end
153
217
 
154
218
  def commit
155
- connection.commit_db_transaction
156
- super
157
- commit_records
219
+ connection.commit_db_transaction if materialized?
220
+ @state.full_commit!
158
221
  end
159
222
  end
160
223
 
@@ -162,43 +225,135 @@ module ActiveRecord
162
225
  def initialize(connection)
163
226
  @stack = []
164
227
  @connection = connection
228
+ @has_unmaterialized_transactions = false
229
+ @materializing_transactions = false
230
+ @lazy_transactions_enabled = true
165
231
  end
166
232
 
167
- def begin_transaction(options = {})
168
- transaction =
169
- if @stack.empty?
170
- RealTransaction.new(@connection, options)
233
+ def begin_transaction(isolation: nil, joinable: true, _lazy: true)
234
+ @connection.lock.synchronize do
235
+ run_commit_callbacks = !current_transaction.joinable?
236
+ transaction =
237
+ if @stack.empty?
238
+ RealTransaction.new(
239
+ @connection,
240
+ isolation: isolation,
241
+ joinable: joinable,
242
+ run_commit_callbacks: run_commit_callbacks
243
+ )
244
+ else
245
+ SavepointTransaction.new(
246
+ @connection,
247
+ "active_record_#{@stack.size}",
248
+ @stack.last,
249
+ isolation: isolation,
250
+ joinable: joinable,
251
+ run_commit_callbacks: run_commit_callbacks
252
+ )
253
+ end
254
+
255
+ if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy
256
+ @has_unmaterialized_transactions = true
171
257
  else
172
- SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options)
258
+ transaction.materialize!
173
259
  end
174
- @stack.push(transaction)
175
- transaction
260
+ @stack.push(transaction)
261
+ transaction
262
+ end
263
+ end
264
+
265
+ def disable_lazy_transactions!
266
+ materialize_transactions
267
+ @lazy_transactions_enabled = false
268
+ end
269
+
270
+ def enable_lazy_transactions!
271
+ @lazy_transactions_enabled = true
272
+ end
273
+
274
+ def lazy_transactions_enabled?
275
+ @lazy_transactions_enabled
276
+ end
277
+
278
+ def materialize_transactions
279
+ return if @materializing_transactions
280
+ return unless @has_unmaterialized_transactions
281
+
282
+ @connection.lock.synchronize do
283
+ begin
284
+ @materializing_transactions = true
285
+ @stack.each { |t| t.materialize! unless t.materialized? }
286
+ ensure
287
+ @materializing_transactions = false
288
+ end
289
+ @has_unmaterialized_transactions = false
290
+ end
176
291
  end
177
292
 
178
293
  def commit_transaction
179
- @stack.pop.commit
294
+ @connection.lock.synchronize do
295
+ transaction = @stack.last
296
+
297
+ begin
298
+ transaction.before_commit_records
299
+ ensure
300
+ @stack.pop
301
+ end
302
+
303
+ transaction.commit
304
+ transaction.commit_records
305
+ end
180
306
  end
181
307
 
182
- def rollback_transaction
183
- @stack.pop.rollback
308
+ def rollback_transaction(transaction = nil)
309
+ @connection.lock.synchronize do
310
+ transaction ||= @stack.pop
311
+ transaction.rollback unless transaction.state.invalidated?
312
+ transaction.rollback_records
313
+ end
184
314
  end
185
315
 
186
- def within_new_transaction(options = {})
187
- transaction = begin_transaction options
188
- yield
189
- rescue Exception => error
190
- rollback_transaction if transaction
191
- raise
192
- ensure
193
- unless error
194
- if Thread.current.status == 'aborting'
316
+ def within_new_transaction(isolation: nil, joinable: true)
317
+ @connection.lock.synchronize do
318
+ transaction = begin_transaction(isolation: isolation, joinable: joinable)
319
+ ret = yield
320
+ completed = true
321
+ ret
322
+ rescue Exception => error
323
+ if transaction
324
+ transaction.state.invalidate! if error.is_a? ActiveRecord::TransactionRollbackError
195
325
  rollback_transaction
196
- else
197
- begin
198
- commit_transaction
199
- rescue Exception
200
- transaction.rollback unless transaction.state.completed?
201
- raise
326
+ after_failure_actions(transaction, error)
327
+ end
328
+
329
+ raise
330
+ ensure
331
+ if transaction
332
+ if error
333
+ # @connection still holds an open or invalid transaction, so we must not
334
+ # put it back in the pool for reuse.
335
+ @connection.throw_away! unless transaction.state.rolledback?
336
+ else
337
+ if Thread.current.status == "aborting"
338
+ rollback_transaction
339
+ else
340
+ if !completed && transaction.written
341
+ ActiveSupport::Deprecation.warn(<<~EOW)
342
+ Using `return`, `break` or `throw` to exit a transaction block is
343
+ deprecated without replacement. If the `throw` came from
344
+ `Timeout.timeout(duration)`, pass an exception class as a second
345
+ argument so it doesn't use `throw` to abort its block. This results
346
+ in the transaction being committed, but in the next release of Rails
347
+ it will rollback.
348
+ EOW
349
+ end
350
+ begin
351
+ commit_transaction
352
+ rescue Exception
353
+ rollback_transaction(transaction) unless transaction.state.completed?
354
+ raise
355
+ end
356
+ end
202
357
  end
203
358
  end
204
359
  end
@@ -214,6 +369,13 @@ module ActiveRecord
214
369
 
215
370
  private
216
371
  NULL_TRANSACTION = NullTransaction.new
372
+
373
+ # Deallocate invalidated prepared statements outside of the transaction
374
+ def after_failure_actions(transaction, error)
375
+ return unless transaction.is_a?(RealTransaction)
376
+ return unless error.is_a?(ActiveRecord::PreparedStatementCacheExpired)
377
+ @connection.clear_cache!
378
+ end
217
379
  end
218
380
  end
219
381
  end