omg-activerecord 8.0.0.alpha1

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 (412) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +355 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README.rdoc +219 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record/aggregations.rb +287 -0
  8. data/lib/active_record/association_relation.rb +50 -0
  9. data/lib/active_record/associations/alias_tracker.rb +90 -0
  10. data/lib/active_record/associations/association.rb +417 -0
  11. data/lib/active_record/associations/association_scope.rb +175 -0
  12. data/lib/active_record/associations/belongs_to_association.rb +163 -0
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
  14. data/lib/active_record/associations/builder/association.rb +170 -0
  15. data/lib/active_record/associations/builder/belongs_to.rb +160 -0
  16. data/lib/active_record/associations/builder/collection_association.rb +80 -0
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +107 -0
  18. data/lib/active_record/associations/builder/has_many.rb +23 -0
  19. data/lib/active_record/associations/builder/has_one.rb +61 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +48 -0
  21. data/lib/active_record/associations/collection_association.rb +535 -0
  22. data/lib/active_record/associations/collection_proxy.rb +1163 -0
  23. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  24. data/lib/active_record/associations/errors.rb +265 -0
  25. data/lib/active_record/associations/foreign_association.rb +40 -0
  26. data/lib/active_record/associations/has_many_association.rb +167 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +232 -0
  28. data/lib/active_record/associations/has_one_association.rb +142 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency/join_association.rb +106 -0
  31. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  32. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  33. data/lib/active_record/associations/join_dependency.rb +301 -0
  34. data/lib/active_record/associations/nested_error.rb +47 -0
  35. data/lib/active_record/associations/preloader/association.rb +316 -0
  36. data/lib/active_record/associations/preloader/batch.rb +48 -0
  37. data/lib/active_record/associations/preloader/branch.rb +153 -0
  38. data/lib/active_record/associations/preloader/through_association.rb +150 -0
  39. data/lib/active_record/associations/preloader.rb +135 -0
  40. data/lib/active_record/associations/singular_association.rb +76 -0
  41. data/lib/active_record/associations/through_association.rb +132 -0
  42. data/lib/active_record/associations.rb +1897 -0
  43. data/lib/active_record/asynchronous_queries_tracker.rb +64 -0
  44. data/lib/active_record/attribute_assignment.rb +82 -0
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +106 -0
  46. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  47. data/lib/active_record/attribute_methods/dirty.rb +262 -0
  48. data/lib/active_record/attribute_methods/primary_key.rb +158 -0
  49. data/lib/active_record/attribute_methods/query.rb +50 -0
  50. data/lib/active_record/attribute_methods/read.rb +46 -0
  51. data/lib/active_record/attribute_methods/serialization.rb +232 -0
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +94 -0
  53. data/lib/active_record/attribute_methods/write.rb +49 -0
  54. data/lib/active_record/attribute_methods.rb +542 -0
  55. data/lib/active_record/attributes.rb +307 -0
  56. data/lib/active_record/autosave_association.rb +586 -0
  57. data/lib/active_record/base.rb +338 -0
  58. data/lib/active_record/callbacks.rb +452 -0
  59. data/lib/active_record/coders/column_serializer.rb +61 -0
  60. data/lib/active_record/coders/json.rb +15 -0
  61. data/lib/active_record/coders/yaml_column.rb +95 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +290 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +210 -0
  64. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +923 -0
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +31 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +747 -0
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +319 -0
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +239 -0
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +24 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +190 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +961 -0
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +106 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1883 -0
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +676 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +1218 -0
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1016 -0
  78. data/lib/active_record/connection_adapters/column.rb +122 -0
  79. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  80. data/lib/active_record/connection_adapters/mysql/column.rb +28 -0
  81. data/lib/active_record/connection_adapters/mysql/database_statements.rb +95 -0
  82. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  83. data/lib/active_record/connection_adapters/mysql/quoting.rb +114 -0
  84. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +106 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +106 -0
  86. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +97 -0
  87. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +300 -0
  88. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  89. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +96 -0
  90. data/lib/active_record/connection_adapters/mysql2_adapter.rb +196 -0
  91. data/lib/active_record/connection_adapters/pool_config.rb +83 -0
  92. data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
  93. data/lib/active_record/connection_adapters/postgresql/column.rb +82 -0
  94. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +231 -0
  95. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +91 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +54 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +31 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +20 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +109 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +42 -0
  112. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  113. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +74 -0
  114. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +124 -0
  115. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  116. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  117. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  118. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +125 -0
  119. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +45 -0
  120. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  121. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  122. data/lib/active_record/connection_adapters/postgresql/oid.rb +38 -0
  123. data/lib/active_record/connection_adapters/postgresql/quoting.rb +238 -0
  124. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +71 -0
  125. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +169 -0
  126. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +392 -0
  127. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +127 -0
  128. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1162 -0
  129. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  130. data/lib/active_record/connection_adapters/postgresql/utils.rb +79 -0
  131. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1182 -0
  132. data/lib/active_record/connection_adapters/schema_cache.rb +478 -0
  133. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  134. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  135. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +145 -0
  136. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  137. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +116 -0
  138. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +37 -0
  139. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +39 -0
  140. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +47 -0
  141. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +221 -0
  142. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +843 -0
  143. data/lib/active_record/connection_adapters/statement_pool.rb +67 -0
  144. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +69 -0
  145. data/lib/active_record/connection_adapters/trilogy_adapter.rb +212 -0
  146. data/lib/active_record/connection_adapters.rb +176 -0
  147. data/lib/active_record/connection_handling.rb +413 -0
  148. data/lib/active_record/core.rb +836 -0
  149. data/lib/active_record/counter_cache.rb +230 -0
  150. data/lib/active_record/database_configurations/connection_url_resolver.rb +105 -0
  151. data/lib/active_record/database_configurations/database_config.rb +104 -0
  152. data/lib/active_record/database_configurations/hash_config.rb +172 -0
  153. data/lib/active_record/database_configurations/url_config.rb +78 -0
  154. data/lib/active_record/database_configurations.rb +309 -0
  155. data/lib/active_record/delegated_type.rb +289 -0
  156. data/lib/active_record/deprecator.rb +7 -0
  157. data/lib/active_record/destroy_association_async_job.rb +38 -0
  158. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  159. data/lib/active_record/dynamic_matchers.rb +121 -0
  160. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  161. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  162. data/lib/active_record/encryption/cipher.rb +53 -0
  163. data/lib/active_record/encryption/config.rb +70 -0
  164. data/lib/active_record/encryption/configurable.rb +60 -0
  165. data/lib/active_record/encryption/context.rb +42 -0
  166. data/lib/active_record/encryption/contexts.rb +76 -0
  167. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  168. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  169. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  170. data/lib/active_record/encryption/encrypted_attribute_type.rb +184 -0
  171. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  172. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  173. data/lib/active_record/encryption/encryptor.rb +177 -0
  174. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  175. data/lib/active_record/encryption/errors.rb +15 -0
  176. data/lib/active_record/encryption/extended_deterministic_queries.rb +159 -0
  177. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  178. data/lib/active_record/encryption/key.rb +28 -0
  179. data/lib/active_record/encryption/key_generator.rb +53 -0
  180. data/lib/active_record/encryption/key_provider.rb +46 -0
  181. data/lib/active_record/encryption/message.rb +33 -0
  182. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  183. data/lib/active_record/encryption/message_serializer.rb +96 -0
  184. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  185. data/lib/active_record/encryption/properties.rb +76 -0
  186. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  187. data/lib/active_record/encryption/scheme.rb +107 -0
  188. data/lib/active_record/encryption.rb +58 -0
  189. data/lib/active_record/enum.rb +424 -0
  190. data/lib/active_record/errors.rb +614 -0
  191. data/lib/active_record/explain.rb +63 -0
  192. data/lib/active_record/explain_registry.rb +37 -0
  193. data/lib/active_record/explain_subscriber.rb +34 -0
  194. data/lib/active_record/fixture_set/file.rb +89 -0
  195. data/lib/active_record/fixture_set/model_metadata.rb +42 -0
  196. data/lib/active_record/fixture_set/render_context.rb +19 -0
  197. data/lib/active_record/fixture_set/table_row.rb +208 -0
  198. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  199. data/lib/active_record/fixtures.rb +850 -0
  200. data/lib/active_record/future_result.rb +182 -0
  201. data/lib/active_record/gem_version.rb +17 -0
  202. data/lib/active_record/inheritance.rb +366 -0
  203. data/lib/active_record/insert_all.rb +328 -0
  204. data/lib/active_record/integration.rb +209 -0
  205. data/lib/active_record/internal_metadata.rb +164 -0
  206. data/lib/active_record/legacy_yaml_adapter.rb +15 -0
  207. data/lib/active_record/locale/en.yml +48 -0
  208. data/lib/active_record/locking/optimistic.rb +228 -0
  209. data/lib/active_record/locking/pessimistic.rb +102 -0
  210. data/lib/active_record/log_subscriber.rb +149 -0
  211. data/lib/active_record/marshalling.rb +56 -0
  212. data/lib/active_record/message_pack.rb +124 -0
  213. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  214. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  215. data/lib/active_record/middleware/database_selector.rb +87 -0
  216. data/lib/active_record/middleware/shard_selector.rb +62 -0
  217. data/lib/active_record/migration/command_recorder.rb +406 -0
  218. data/lib/active_record/migration/compatibility.rb +490 -0
  219. data/lib/active_record/migration/default_strategy.rb +22 -0
  220. data/lib/active_record/migration/execution_strategy.rb +19 -0
  221. data/lib/active_record/migration/join_table.rb +16 -0
  222. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  223. data/lib/active_record/migration.rb +1626 -0
  224. data/lib/active_record/model_schema.rb +635 -0
  225. data/lib/active_record/nested_attributes.rb +633 -0
  226. data/lib/active_record/no_touching.rb +65 -0
  227. data/lib/active_record/normalization.rb +163 -0
  228. data/lib/active_record/persistence.rb +968 -0
  229. data/lib/active_record/promise.rb +84 -0
  230. data/lib/active_record/query_cache.rb +56 -0
  231. data/lib/active_record/query_logs.rb +247 -0
  232. data/lib/active_record/query_logs_formatter.rb +30 -0
  233. data/lib/active_record/querying.rb +122 -0
  234. data/lib/active_record/railtie.rb +440 -0
  235. data/lib/active_record/railties/console_sandbox.rb +5 -0
  236. data/lib/active_record/railties/controller_runtime.rb +65 -0
  237. data/lib/active_record/railties/databases.rake +641 -0
  238. data/lib/active_record/railties/job_runtime.rb +23 -0
  239. data/lib/active_record/readonly_attributes.rb +66 -0
  240. data/lib/active_record/reflection.rb +1287 -0
  241. data/lib/active_record/relation/batches/batch_enumerator.rb +115 -0
  242. data/lib/active_record/relation/batches.rb +491 -0
  243. data/lib/active_record/relation/calculations.rb +679 -0
  244. data/lib/active_record/relation/delegation.rb +154 -0
  245. data/lib/active_record/relation/finder_methods.rb +661 -0
  246. data/lib/active_record/relation/from_clause.rb +30 -0
  247. data/lib/active_record/relation/merger.rb +192 -0
  248. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  249. data/lib/active_record/relation/predicate_builder/association_query_value.rb +76 -0
  250. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  251. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +60 -0
  252. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  253. data/lib/active_record/relation/predicate_builder/relation_handler.rb +24 -0
  254. data/lib/active_record/relation/predicate_builder.rb +181 -0
  255. data/lib/active_record/relation/query_attribute.rb +68 -0
  256. data/lib/active_record/relation/query_methods.rb +2235 -0
  257. data/lib/active_record/relation/record_fetch_warning.rb +52 -0
  258. data/lib/active_record/relation/spawn_methods.rb +78 -0
  259. data/lib/active_record/relation/where_clause.rb +218 -0
  260. data/lib/active_record/relation.rb +1495 -0
  261. data/lib/active_record/result.rb +249 -0
  262. data/lib/active_record/runtime_registry.rb +82 -0
  263. data/lib/active_record/sanitization.rb +254 -0
  264. data/lib/active_record/schema.rb +77 -0
  265. data/lib/active_record/schema_dumper.rb +364 -0
  266. data/lib/active_record/schema_migration.rb +106 -0
  267. data/lib/active_record/scoping/default.rb +205 -0
  268. data/lib/active_record/scoping/named.rb +202 -0
  269. data/lib/active_record/scoping.rb +136 -0
  270. data/lib/active_record/secure_password.rb +60 -0
  271. data/lib/active_record/secure_token.rb +66 -0
  272. data/lib/active_record/serialization.rb +29 -0
  273. data/lib/active_record/signed_id.rb +137 -0
  274. data/lib/active_record/statement_cache.rb +164 -0
  275. data/lib/active_record/store.rb +299 -0
  276. data/lib/active_record/suppressor.rb +59 -0
  277. data/lib/active_record/table_metadata.rb +85 -0
  278. data/lib/active_record/tasks/database_tasks.rb +681 -0
  279. data/lib/active_record/tasks/mysql_database_tasks.rb +120 -0
  280. data/lib/active_record/tasks/postgresql_database_tasks.rb +147 -0
  281. data/lib/active_record/tasks/sqlite_database_tasks.rb +89 -0
  282. data/lib/active_record/test_databases.rb +24 -0
  283. data/lib/active_record/test_fixtures.rb +321 -0
  284. data/lib/active_record/testing/query_assertions.rb +121 -0
  285. data/lib/active_record/timestamp.rb +177 -0
  286. data/lib/active_record/token_for.rb +123 -0
  287. data/lib/active_record/touch_later.rb +70 -0
  288. data/lib/active_record/transaction.rb +132 -0
  289. data/lib/active_record/transactions.rb +523 -0
  290. data/lib/active_record/translation.rb +22 -0
  291. data/lib/active_record/type/adapter_specific_registry.rb +144 -0
  292. data/lib/active_record/type/date.rb +9 -0
  293. data/lib/active_record/type/date_time.rb +9 -0
  294. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  295. data/lib/active_record/type/hash_lookup_type_map.rb +57 -0
  296. data/lib/active_record/type/internal/timezone.rb +22 -0
  297. data/lib/active_record/type/json.rb +30 -0
  298. data/lib/active_record/type/serialized.rb +76 -0
  299. data/lib/active_record/type/text.rb +11 -0
  300. data/lib/active_record/type/time.rb +35 -0
  301. data/lib/active_record/type/type_map.rb +58 -0
  302. data/lib/active_record/type/unsigned_integer.rb +16 -0
  303. data/lib/active_record/type.rb +83 -0
  304. data/lib/active_record/type_caster/connection.rb +33 -0
  305. data/lib/active_record/type_caster/map.rb +23 -0
  306. data/lib/active_record/type_caster.rb +9 -0
  307. data/lib/active_record/validations/absence.rb +25 -0
  308. data/lib/active_record/validations/associated.rb +65 -0
  309. data/lib/active_record/validations/length.rb +26 -0
  310. data/lib/active_record/validations/numericality.rb +36 -0
  311. data/lib/active_record/validations/presence.rb +45 -0
  312. data/lib/active_record/validations/uniqueness.rb +295 -0
  313. data/lib/active_record/validations.rb +101 -0
  314. data/lib/active_record/version.rb +10 -0
  315. data/lib/active_record.rb +616 -0
  316. data/lib/arel/alias_predication.rb +9 -0
  317. data/lib/arel/attributes/attribute.rb +33 -0
  318. data/lib/arel/collectors/bind.rb +31 -0
  319. data/lib/arel/collectors/composite.rb +46 -0
  320. data/lib/arel/collectors/plain_string.rb +20 -0
  321. data/lib/arel/collectors/sql_string.rb +27 -0
  322. data/lib/arel/collectors/substitute_binds.rb +35 -0
  323. data/lib/arel/crud.rb +48 -0
  324. data/lib/arel/delete_manager.rb +32 -0
  325. data/lib/arel/errors.rb +19 -0
  326. data/lib/arel/expressions.rb +29 -0
  327. data/lib/arel/factory_methods.rb +53 -0
  328. data/lib/arel/filter_predications.rb +9 -0
  329. data/lib/arel/insert_manager.rb +48 -0
  330. data/lib/arel/math.rb +45 -0
  331. data/lib/arel/nodes/ascending.rb +23 -0
  332. data/lib/arel/nodes/binary.rb +125 -0
  333. data/lib/arel/nodes/bind_param.rb +44 -0
  334. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  335. data/lib/arel/nodes/case.rb +55 -0
  336. data/lib/arel/nodes/casted.rb +62 -0
  337. data/lib/arel/nodes/comment.rb +29 -0
  338. data/lib/arel/nodes/count.rb +12 -0
  339. data/lib/arel/nodes/cte.rb +36 -0
  340. data/lib/arel/nodes/delete_statement.rb +44 -0
  341. data/lib/arel/nodes/descending.rb +23 -0
  342. data/lib/arel/nodes/equality.rb +15 -0
  343. data/lib/arel/nodes/extract.rb +24 -0
  344. data/lib/arel/nodes/false.rb +16 -0
  345. data/lib/arel/nodes/filter.rb +10 -0
  346. data/lib/arel/nodes/fragments.rb +35 -0
  347. data/lib/arel/nodes/full_outer_join.rb +8 -0
  348. data/lib/arel/nodes/function.rb +45 -0
  349. data/lib/arel/nodes/grouping.rb +11 -0
  350. data/lib/arel/nodes/homogeneous_in.rb +68 -0
  351. data/lib/arel/nodes/in.rb +15 -0
  352. data/lib/arel/nodes/infix_operation.rb +92 -0
  353. data/lib/arel/nodes/inner_join.rb +8 -0
  354. data/lib/arel/nodes/insert_statement.rb +37 -0
  355. data/lib/arel/nodes/join_source.rb +20 -0
  356. data/lib/arel/nodes/leading_join.rb +8 -0
  357. data/lib/arel/nodes/matches.rb +18 -0
  358. data/lib/arel/nodes/named_function.rb +23 -0
  359. data/lib/arel/nodes/nary.rb +39 -0
  360. data/lib/arel/nodes/node.rb +161 -0
  361. data/lib/arel/nodes/node_expression.rb +13 -0
  362. data/lib/arel/nodes/ordering.rb +27 -0
  363. data/lib/arel/nodes/outer_join.rb +8 -0
  364. data/lib/arel/nodes/over.rb +15 -0
  365. data/lib/arel/nodes/regexp.rb +16 -0
  366. data/lib/arel/nodes/right_outer_join.rb +8 -0
  367. data/lib/arel/nodes/select_core.rb +67 -0
  368. data/lib/arel/nodes/select_statement.rb +41 -0
  369. data/lib/arel/nodes/sql_literal.rb +32 -0
  370. data/lib/arel/nodes/string_join.rb +11 -0
  371. data/lib/arel/nodes/table_alias.rb +35 -0
  372. data/lib/arel/nodes/terminal.rb +16 -0
  373. data/lib/arel/nodes/true.rb +16 -0
  374. data/lib/arel/nodes/unary.rb +44 -0
  375. data/lib/arel/nodes/unary_operation.rb +20 -0
  376. data/lib/arel/nodes/unqualified_column.rb +22 -0
  377. data/lib/arel/nodes/update_statement.rb +46 -0
  378. data/lib/arel/nodes/values_list.rb +9 -0
  379. data/lib/arel/nodes/window.rb +126 -0
  380. data/lib/arel/nodes/with.rb +11 -0
  381. data/lib/arel/nodes.rb +75 -0
  382. data/lib/arel/order_predications.rb +13 -0
  383. data/lib/arel/predications.rb +260 -0
  384. data/lib/arel/select_manager.rb +276 -0
  385. data/lib/arel/table.rb +121 -0
  386. data/lib/arel/tree_manager.rb +65 -0
  387. data/lib/arel/update_manager.rb +49 -0
  388. data/lib/arel/visitors/dot.rb +299 -0
  389. data/lib/arel/visitors/mysql.rb +111 -0
  390. data/lib/arel/visitors/postgresql.rb +99 -0
  391. data/lib/arel/visitors/sqlite.rb +38 -0
  392. data/lib/arel/visitors/to_sql.rb +1033 -0
  393. data/lib/arel/visitors/visitor.rb +45 -0
  394. data/lib/arel/visitors.rb +13 -0
  395. data/lib/arel/window_predications.rb +9 -0
  396. data/lib/arel.rb +73 -0
  397. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  398. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  399. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  400. data/lib/rails/generators/active_record/migration/migration_generator.rb +76 -0
  401. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +29 -0
  402. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  403. data/lib/rails/generators/active_record/migration.rb +54 -0
  404. data/lib/rails/generators/active_record/model/USAGE +113 -0
  405. data/lib/rails/generators/active_record/model/model_generator.rb +94 -0
  406. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  407. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  408. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  409. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  410. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  411. data/lib/rails/generators/active_record.rb +19 -0
  412. metadata +505 -0
@@ -0,0 +1,676 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/digest"
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ # = Active Record Connection Adapters Transaction State
8
+ class TransactionState
9
+ def initialize(state = nil)
10
+ @state = state
11
+ @children = nil
12
+ end
13
+
14
+ def add_child(state)
15
+ @children ||= []
16
+ @children << state
17
+ end
18
+
19
+ def finalized?
20
+ @state
21
+ end
22
+
23
+ def committed?
24
+ @state == :committed || @state == :fully_committed
25
+ end
26
+
27
+ def fully_committed?
28
+ @state == :fully_committed
29
+ end
30
+
31
+ def rolledback?
32
+ @state == :rolledback || @state == :fully_rolledback
33
+ end
34
+
35
+ def fully_rolledback?
36
+ @state == :fully_rolledback
37
+ end
38
+
39
+ def invalidated?
40
+ @state == :invalidated
41
+ end
42
+
43
+ def fully_completed?
44
+ completed?
45
+ end
46
+
47
+ def completed?
48
+ committed? || rolledback?
49
+ end
50
+
51
+ def rollback!
52
+ @children&.each { |c| c.rollback! }
53
+ @state = :rolledback
54
+ end
55
+
56
+ def full_rollback!
57
+ @children&.each { |c| c.rollback! }
58
+ @state = :fully_rolledback
59
+ end
60
+
61
+ def invalidate!
62
+ @children&.each { |c| c.invalidate! }
63
+ @state = :invalidated
64
+ end
65
+
66
+ def commit!
67
+ @state = :committed
68
+ end
69
+
70
+ def full_commit!
71
+ @state = :fully_committed
72
+ end
73
+
74
+ def nullify!
75
+ @state = nil
76
+ end
77
+ end
78
+
79
+ class TransactionInstrumenter
80
+ def initialize(payload = {})
81
+ @handle = nil
82
+ @started = false
83
+ @payload = nil
84
+ @base_payload = payload
85
+ end
86
+
87
+ class InstrumentationNotStartedError < ActiveRecordError; end
88
+ class InstrumentationAlreadyStartedError < ActiveRecordError; end
89
+
90
+ def start
91
+ raise InstrumentationAlreadyStartedError.new("Called start on an already started transaction") if @started
92
+ @started = true
93
+
94
+ ActiveSupport::Notifications.instrument("start_transaction.active_record", @base_payload)
95
+
96
+ @payload = @base_payload.dup # We dup because the payload for a given event is mutated later to add the outcome.
97
+ @handle = ActiveSupport::Notifications.instrumenter.build_handle("transaction.active_record", @payload)
98
+ @handle.start
99
+ end
100
+
101
+ def finish(outcome)
102
+ raise InstrumentationNotStartedError.new("Called finish on a transaction that hasn't started") unless @started
103
+ @started = false
104
+
105
+ @payload[:outcome] = outcome
106
+ @handle.finish
107
+ end
108
+ end
109
+
110
+ class NullTransaction # :nodoc:
111
+ def state; end
112
+ def closed?; true; end
113
+ def open?; false; end
114
+ def joinable?; false; end
115
+ def add_record(record, _ = true); end
116
+ def restartable?; false; end
117
+ def dirty?; false; end
118
+ def dirty!; end
119
+ def invalidated?; false; end
120
+ def invalidate!; end
121
+ def materialized?; false; end
122
+ def before_commit; yield; end
123
+ def after_commit; yield; end
124
+ def after_rollback; end
125
+ def user_transaction; ActiveRecord::Transaction::NULL_TRANSACTION; end
126
+ end
127
+
128
+ class Transaction # :nodoc:
129
+ class Callback # :nodoc:
130
+ def initialize(event, callback)
131
+ @event = event
132
+ @callback = callback
133
+ end
134
+
135
+ def before_commit
136
+ @callback.call if @event == :before_commit
137
+ end
138
+
139
+ def after_commit
140
+ @callback.call if @event == :after_commit
141
+ end
142
+
143
+ def after_rollback
144
+ @callback.call if @event == :after_rollback
145
+ end
146
+ end
147
+
148
+ attr_reader :connection, :state, :savepoint_name, :isolation_level, :user_transaction
149
+ attr_accessor :written
150
+
151
+ delegate :invalidate!, :invalidated?, to: :@state
152
+
153
+ def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false)
154
+ super()
155
+ @connection = connection
156
+ @state = TransactionState.new
157
+ @callbacks = nil
158
+ @records = nil
159
+ @isolation_level = isolation
160
+ @materialized = false
161
+ @joinable = joinable
162
+ @run_commit_callbacks = run_commit_callbacks
163
+ @lazy_enrollment_records = nil
164
+ @dirty = false
165
+ @user_transaction = joinable ? ActiveRecord::Transaction.new(self) : ActiveRecord::Transaction::NULL_TRANSACTION
166
+ @instrumenter = TransactionInstrumenter.new(connection: connection, transaction: @user_transaction)
167
+ end
168
+
169
+ def dirty!
170
+ @dirty = true
171
+ end
172
+
173
+ def dirty?
174
+ @dirty
175
+ end
176
+
177
+ def open?
178
+ true
179
+ end
180
+
181
+ def closed?
182
+ false
183
+ end
184
+
185
+ def add_record(record, ensure_finalize = true)
186
+ @records ||= []
187
+ if ensure_finalize
188
+ @records << record
189
+ else
190
+ @lazy_enrollment_records ||= ObjectSpace::WeakMap.new
191
+ @lazy_enrollment_records[record] = record
192
+ end
193
+ end
194
+
195
+ def before_commit(&block)
196
+ if @state.finalized?
197
+ raise ActiveRecordError, "Cannot register callbacks on a finalized transaction"
198
+ end
199
+
200
+ (@callbacks ||= []) << Callback.new(:before_commit, block)
201
+ end
202
+
203
+ def after_commit(&block)
204
+ if @state.finalized?
205
+ raise ActiveRecordError, "Cannot register callbacks on a finalized transaction"
206
+ end
207
+
208
+ (@callbacks ||= []) << Callback.new(:after_commit, block)
209
+ end
210
+
211
+ def after_rollback(&block)
212
+ if @state.finalized?
213
+ raise ActiveRecordError, "Cannot register callbacks on a finalized transaction"
214
+ end
215
+
216
+ (@callbacks ||= []) << Callback.new(:after_rollback, block)
217
+ end
218
+
219
+ def records
220
+ if @lazy_enrollment_records
221
+ @records.concat @lazy_enrollment_records.values
222
+ @lazy_enrollment_records = nil
223
+ end
224
+ @records
225
+ end
226
+
227
+ # Can this transaction's current state be recreated by
228
+ # rollback+begin ?
229
+ def restartable?
230
+ joinable? && !dirty?
231
+ end
232
+
233
+ def incomplete!
234
+ @instrumenter.finish(:incomplete) if materialized?
235
+ end
236
+
237
+ def materialize!
238
+ @materialized = true
239
+ @instrumenter.start
240
+ end
241
+
242
+ def materialized?
243
+ @materialized
244
+ end
245
+
246
+ def restore!
247
+ if materialized?
248
+ incomplete!
249
+ @materialized = false
250
+ materialize!
251
+ end
252
+ end
253
+
254
+ def rollback_records
255
+ if records
256
+ begin
257
+ ite = unique_records
258
+
259
+ instances_to_run_callbacks_on = prepare_instances_to_run_callbacks_on(ite)
260
+
261
+ run_action_on_records(ite, instances_to_run_callbacks_on) do |record, should_run_callbacks|
262
+ record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
263
+ end
264
+ ensure
265
+ ite&.each do |i|
266
+ i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
267
+ end
268
+ end
269
+ end
270
+
271
+ @callbacks&.each(&:after_rollback)
272
+ end
273
+
274
+ def before_commit_records
275
+ if @run_commit_callbacks
276
+ if records
277
+ if ActiveRecord.before_committed_on_all_records
278
+ ite = unique_records
279
+
280
+ instances_to_run_callbacks_on = records.each_with_object({}) do |record, candidates|
281
+ candidates[record] = record
282
+ end
283
+
284
+ run_action_on_records(ite, instances_to_run_callbacks_on) do |record, should_run_callbacks|
285
+ record.before_committed! if should_run_callbacks
286
+ end
287
+ else
288
+ records.uniq.each(&:before_committed!)
289
+ end
290
+ end
291
+
292
+ @callbacks&.each(&:before_commit)
293
+ end
294
+ # Note: When @run_commit_callbacks is false #commit_records takes care of appending
295
+ # remaining callbacks to the parent transaction
296
+ end
297
+
298
+ def commit_records
299
+ if records
300
+ begin
301
+ ite = unique_records
302
+
303
+ if @run_commit_callbacks
304
+ instances_to_run_callbacks_on = prepare_instances_to_run_callbacks_on(ite)
305
+
306
+ run_action_on_records(ite, instances_to_run_callbacks_on) do |record, should_run_callbacks|
307
+ record.committed!(should_run_callbacks: should_run_callbacks)
308
+ end
309
+ else
310
+ while record = ite.shift
311
+ # if not running callbacks, only adds the record to the parent transaction
312
+ connection.add_transaction_record(record)
313
+ end
314
+ end
315
+ ensure
316
+ ite&.each { |i| i.committed!(should_run_callbacks: false) }
317
+ end
318
+ end
319
+
320
+ if @run_commit_callbacks
321
+ @callbacks&.each(&:after_commit)
322
+ elsif @callbacks
323
+ connection.current_transaction.append_callbacks(@callbacks)
324
+ end
325
+ end
326
+
327
+ def full_rollback?; true; end
328
+ def joinable?; @joinable; end
329
+
330
+ protected
331
+ def append_callbacks(callbacks) # :nodoc:
332
+ (@callbacks ||= []).concat(callbacks)
333
+ end
334
+
335
+ private
336
+ def unique_records
337
+ records.uniq(&:__id__)
338
+ end
339
+
340
+ def run_action_on_records(records, instances_to_run_callbacks_on)
341
+ while record = records.shift
342
+ should_run_callbacks = record.__id__ == instances_to_run_callbacks_on[record].__id__
343
+
344
+ yield record, should_run_callbacks
345
+ end
346
+ end
347
+
348
+ def prepare_instances_to_run_callbacks_on(records)
349
+ records.each_with_object({}) do |record, candidates|
350
+ next unless record.trigger_transactional_callbacks?
351
+
352
+ earlier_saved_candidate = candidates[record]
353
+
354
+ next if earlier_saved_candidate && record.class.run_commit_callbacks_on_first_saved_instances_in_transaction
355
+
356
+ # If the candidate instance destroyed itself in the database, then
357
+ # instances which were added to the transaction afterwards, and which
358
+ # think they updated themselves, are wrong. They should not replace
359
+ # our candidate as an instance to run callbacks on
360
+ next if earlier_saved_candidate&.destroyed? && !record.destroyed?
361
+
362
+ # If the candidate instance was created inside of this transaction,
363
+ # then instances which were subsequently loaded from the database
364
+ # and updated need that state transferred to them so that
365
+ # the after_create_commit callbacks are run
366
+ record._new_record_before_last_commit = true if earlier_saved_candidate&._new_record_before_last_commit
367
+
368
+ # The last instance to save itself is likeliest to have internal
369
+ # state that matches what's committed to the database
370
+ candidates[record] = record
371
+ end
372
+ end
373
+ end
374
+
375
+ # = Active Record Restart Parent \Transaction
376
+ class RestartParentTransaction < Transaction
377
+ def initialize(connection, parent_transaction, **options)
378
+ super(connection, **options)
379
+
380
+ @parent = parent_transaction
381
+
382
+ if isolation_level
383
+ raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
384
+ end
385
+
386
+ @parent.state.add_child(@state)
387
+ end
388
+
389
+ delegate :materialize!, :materialized?, :restart, to: :@parent
390
+
391
+ def rollback
392
+ @state.rollback!
393
+ @parent.restart
394
+ end
395
+
396
+ def commit
397
+ @state.commit!
398
+ end
399
+
400
+ def full_rollback?; false; end
401
+ end
402
+
403
+ # = Active Record Savepoint \Transaction
404
+ class SavepointTransaction < Transaction
405
+ def initialize(connection, savepoint_name, parent_transaction, **options)
406
+ super(connection, **options)
407
+
408
+ parent_transaction.state.add_child(@state)
409
+
410
+ if isolation_level
411
+ raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
412
+ end
413
+
414
+ @savepoint_name = savepoint_name
415
+ end
416
+
417
+ def materialize!
418
+ connection.create_savepoint(savepoint_name)
419
+ super
420
+ end
421
+
422
+ def restart
423
+ return unless materialized?
424
+
425
+ @instrumenter.finish(:restart)
426
+ @instrumenter.start
427
+
428
+ connection.rollback_to_savepoint(savepoint_name)
429
+ end
430
+
431
+ def rollback
432
+ unless @state.invalidated?
433
+ connection.rollback_to_savepoint(savepoint_name) if materialized? && connection.active?
434
+ end
435
+ @state.rollback!
436
+ @instrumenter.finish(:rollback) if materialized?
437
+ end
438
+
439
+ def commit
440
+ connection.release_savepoint(savepoint_name) if materialized?
441
+ @state.commit!
442
+ @instrumenter.finish(:commit) if materialized?
443
+ end
444
+
445
+ def full_rollback?; false; end
446
+ end
447
+
448
+ # = Active Record Real \Transaction
449
+ class RealTransaction < Transaction
450
+ def materialize!
451
+ if joinable?
452
+ if isolation_level
453
+ connection.begin_isolated_db_transaction(isolation_level)
454
+ else
455
+ connection.begin_db_transaction
456
+ end
457
+ else
458
+ connection.begin_deferred_transaction(isolation_level)
459
+ end
460
+
461
+ super
462
+ end
463
+
464
+ def restart
465
+ return unless materialized?
466
+
467
+ @instrumenter.finish(:restart)
468
+
469
+ if connection.supports_restart_db_transaction?
470
+ @instrumenter.start
471
+ connection.restart_db_transaction
472
+ else
473
+ connection.rollback_db_transaction
474
+ materialize!
475
+ end
476
+ end
477
+
478
+ def rollback
479
+ if materialized?
480
+ connection.rollback_db_transaction
481
+ connection.reset_isolation_level if isolation_level
482
+ end
483
+ @state.full_rollback!
484
+ @instrumenter.finish(:rollback) if materialized?
485
+ end
486
+
487
+ def commit
488
+ if materialized?
489
+ connection.commit_db_transaction
490
+ connection.reset_isolation_level if isolation_level
491
+ end
492
+ @state.full_commit!
493
+ @instrumenter.finish(:commit) if materialized?
494
+ end
495
+ end
496
+
497
+ class TransactionManager # :nodoc:
498
+ def initialize(connection)
499
+ @stack = []
500
+ @connection = connection
501
+ @has_unmaterialized_transactions = false
502
+ @materializing_transactions = false
503
+ @lazy_transactions_enabled = true
504
+ end
505
+
506
+ def begin_transaction(isolation: nil, joinable: true, _lazy: true)
507
+ @connection.lock.synchronize do
508
+ run_commit_callbacks = !current_transaction.joinable?
509
+ transaction =
510
+ if @stack.empty?
511
+ RealTransaction.new(
512
+ @connection,
513
+ isolation: isolation,
514
+ joinable: joinable,
515
+ run_commit_callbacks: run_commit_callbacks
516
+ )
517
+ elsif current_transaction.restartable?
518
+ RestartParentTransaction.new(
519
+ @connection,
520
+ current_transaction,
521
+ isolation: isolation,
522
+ joinable: joinable,
523
+ run_commit_callbacks: run_commit_callbacks
524
+ )
525
+ else
526
+ SavepointTransaction.new(
527
+ @connection,
528
+ "active_record_#{@stack.size}",
529
+ current_transaction,
530
+ isolation: isolation,
531
+ joinable: joinable,
532
+ run_commit_callbacks: run_commit_callbacks
533
+ )
534
+ end
535
+
536
+ unless transaction.materialized?
537
+ if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy
538
+ @has_unmaterialized_transactions = true
539
+ else
540
+ transaction.materialize!
541
+ end
542
+ end
543
+ @stack.push(transaction)
544
+ transaction
545
+ end
546
+ end
547
+
548
+ def disable_lazy_transactions!
549
+ materialize_transactions
550
+ @lazy_transactions_enabled = false
551
+ end
552
+
553
+ def enable_lazy_transactions!
554
+ @lazy_transactions_enabled = true
555
+ end
556
+
557
+ def lazy_transactions_enabled?
558
+ @lazy_transactions_enabled
559
+ end
560
+
561
+ def dirty_current_transaction
562
+ current_transaction.dirty!
563
+ end
564
+
565
+ def restore_transactions
566
+ return false unless restorable?
567
+
568
+ @stack.each(&:restore!)
569
+
570
+ true
571
+ end
572
+
573
+ def restorable?
574
+ @stack.none?(&:dirty?)
575
+ end
576
+
577
+ def materialize_transactions
578
+ return if @materializing_transactions
579
+
580
+ if @has_unmaterialized_transactions
581
+ @connection.lock.synchronize do
582
+ begin
583
+ @materializing_transactions = true
584
+ @stack.each { |t| t.materialize! unless t.materialized? }
585
+ ensure
586
+ @materializing_transactions = false
587
+ end
588
+ @has_unmaterialized_transactions = false
589
+ end
590
+ end
591
+ end
592
+
593
+ def commit_transaction
594
+ @connection.lock.synchronize do
595
+ transaction = @stack.last
596
+
597
+ begin
598
+ transaction.before_commit_records
599
+ ensure
600
+ @stack.pop
601
+ end
602
+
603
+ dirty_current_transaction if transaction.dirty?
604
+
605
+ transaction.commit
606
+ transaction.commit_records
607
+ end
608
+ end
609
+
610
+ def rollback_transaction(transaction = nil)
611
+ @connection.lock.synchronize do
612
+ transaction ||= @stack.last
613
+ begin
614
+ transaction.rollback
615
+ ensure
616
+ @stack.pop if @stack.last == transaction
617
+ end
618
+ transaction.rollback_records
619
+ end
620
+ end
621
+
622
+ def within_new_transaction(isolation: nil, joinable: true)
623
+ @connection.lock.synchronize do
624
+ transaction = begin_transaction(isolation: isolation, joinable: joinable)
625
+ begin
626
+ yield transaction.user_transaction
627
+ rescue Exception => error
628
+ rollback_transaction
629
+ after_failure_actions(transaction, error)
630
+
631
+ raise
632
+ ensure
633
+ unless error
634
+ if Thread.current.status == "aborting"
635
+ rollback_transaction
636
+ else
637
+ begin
638
+ commit_transaction
639
+ rescue ActiveRecord::ConnectionFailed
640
+ transaction.invalidate! unless transaction.state.completed?
641
+ raise
642
+ rescue Exception
643
+ rollback_transaction(transaction) unless transaction.state.completed?
644
+ raise
645
+ end
646
+ end
647
+ end
648
+ end
649
+ ensure
650
+ unless transaction&.state&.completed?
651
+ @connection.throw_away!
652
+ transaction&.incomplete!
653
+ end
654
+ end
655
+ end
656
+
657
+ def open_transactions
658
+ @stack.size
659
+ end
660
+
661
+ def current_transaction
662
+ @stack.last || NULL_TRANSACTION
663
+ end
664
+
665
+ private
666
+ NULL_TRANSACTION = NullTransaction.new.freeze
667
+
668
+ # Deallocate invalidated prepared statements outside of the transaction
669
+ def after_failure_actions(transaction, error)
670
+ return unless transaction.is_a?(RealTransaction)
671
+ return unless error.is_a?(ActiveRecord::PreparedStatementCacheExpired)
672
+ @connection.clear_cache!
673
+ end
674
+ end
675
+ end
676
+ end