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,413 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ # = Active Record Connection Handling
5
+ module ConnectionHandling
6
+ RAILS_ENV = -> { (Rails.env if defined?(Rails.env)) || ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence }
7
+ DEFAULT_ENV = -> { RAILS_ENV.call || "default_env" }
8
+
9
+ # Establishes the connection to the database. Accepts a hash as input where
10
+ # the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
11
+ # example for regular databases (MySQL, PostgreSQL, etc):
12
+ #
13
+ # ActiveRecord::Base.establish_connection(
14
+ # adapter: "mysql2",
15
+ # host: "localhost",
16
+ # username: "myuser",
17
+ # password: "mypass",
18
+ # database: "somedatabase"
19
+ # )
20
+ #
21
+ # Example for SQLite database:
22
+ #
23
+ # ActiveRecord::Base.establish_connection(
24
+ # adapter: "sqlite3",
25
+ # database: "path/to/dbfile"
26
+ # )
27
+ #
28
+ # Also accepts keys as strings (for parsing from YAML for example):
29
+ #
30
+ # ActiveRecord::Base.establish_connection(
31
+ # "adapter" => "sqlite3",
32
+ # "database" => "path/to/dbfile"
33
+ # )
34
+ #
35
+ # Or a URL:
36
+ #
37
+ # ActiveRecord::Base.establish_connection(
38
+ # "postgres://myuser:mypass@localhost/somedatabase"
39
+ # )
40
+ #
41
+ # In case {ActiveRecord::Base.configurations}[rdoc-ref:Core.configurations]
42
+ # is set (\Rails automatically loads the contents of config/database.yml into it),
43
+ # a symbol can also be given as argument, representing a key in the
44
+ # configuration hash:
45
+ #
46
+ # ActiveRecord::Base.establish_connection(:production)
47
+ #
48
+ # The exceptions AdapterNotSpecified, AdapterNotFound, and +ArgumentError+
49
+ # may be returned on an error.
50
+ def establish_connection(config_or_env = nil)
51
+ config_or_env ||= DEFAULT_ENV.call.to_sym
52
+ db_config = resolve_config_for_connection(config_or_env)
53
+ connection_handler.establish_connection(db_config, owner_name: self, role: current_role, shard: current_shard)
54
+ end
55
+
56
+ # Connects a model to the databases specified. The +database+ keyword
57
+ # takes a hash consisting of a +role+ and a +database_key+.
58
+ #
59
+ # This will look up the database config using the +database_key+ and
60
+ # establish a connection to that config.
61
+ #
62
+ # class AnimalsModel < ApplicationRecord
63
+ # self.abstract_class = true
64
+ #
65
+ # connects_to database: { writing: :primary, reading: :primary_replica }
66
+ # end
67
+ #
68
+ # +connects_to+ also supports horizontal sharding. The horizontal sharding API
69
+ # supports read replicas as well. You can connect a model to a list of shards like this:
70
+ #
71
+ # class AnimalsModel < ApplicationRecord
72
+ # self.abstract_class = true
73
+ #
74
+ # connects_to shards: {
75
+ # default: { writing: :primary, reading: :primary_replica },
76
+ # shard_two: { writing: :primary_shard_two, reading: :primary_shard_replica_two }
77
+ # }
78
+ # end
79
+ #
80
+ # Returns an array of database connections.
81
+ def connects_to(database: {}, shards: {})
82
+ raise NotImplementedError, "`connects_to` can only be called on ActiveRecord::Base or abstract classes" unless self == Base || abstract_class?
83
+
84
+ if database.present? && shards.present?
85
+ raise ArgumentError, "`connects_to` can only accept a `database` or `shards` argument, but not both arguments."
86
+ end
87
+
88
+ connections = []
89
+
90
+ @shard_keys = shards.keys
91
+
92
+ if shards.empty?
93
+ shards[:default] = database
94
+ end
95
+
96
+ self.default_shard = shards.keys.first
97
+
98
+ shards.each do |shard, database_keys|
99
+ database_keys.each do |role, database_key|
100
+ db_config = resolve_config_for_connection(database_key)
101
+
102
+ self.connection_class = true
103
+ connections << connection_handler.establish_connection(db_config, owner_name: self, role: role, shard: shard.to_sym)
104
+ end
105
+ end
106
+
107
+ connections
108
+ end
109
+
110
+ # Connects to a role (e.g. writing, reading, or a custom role) and/or
111
+ # shard for the duration of the block. At the end of the block the
112
+ # connection will be returned to the original role / shard.
113
+ #
114
+ # If only a role is passed, Active Record will look up the connection
115
+ # based on the requested role. If a non-established role is requested
116
+ # an +ActiveRecord::ConnectionNotEstablished+ error will be raised:
117
+ #
118
+ # ActiveRecord::Base.connected_to(role: :writing) do
119
+ # Dog.create! # creates dog using dog writing connection
120
+ # end
121
+ #
122
+ # ActiveRecord::Base.connected_to(role: :reading) do
123
+ # Dog.create! # throws exception because we're on a replica
124
+ # end
125
+ #
126
+ # When swapping to a shard, the role must be passed as well. If a non-existent
127
+ # shard is passed, an +ActiveRecord::ConnectionNotEstablished+ error will be
128
+ # raised.
129
+ #
130
+ # When a shard and role is passed, Active Record will first lookup the role,
131
+ # and then look up the connection by shard key.
132
+ #
133
+ # ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one_replica) do
134
+ # Dog.first # finds first Dog record stored on the shard one replica
135
+ # end
136
+ def connected_to(role: nil, shard: nil, prevent_writes: false, &blk)
137
+ if self != Base && !abstract_class
138
+ raise NotImplementedError, "calling `connected_to` is only allowed on ActiveRecord::Base or abstract classes."
139
+ end
140
+
141
+ if !connection_class? && !primary_class?
142
+ raise NotImplementedError, "calling `connected_to` is only allowed on the abstract class that established the connection."
143
+ end
144
+
145
+ unless role || shard
146
+ raise ArgumentError, "must provide a `shard` and/or `role`."
147
+ end
148
+
149
+ with_role_and_shard(role, shard, prevent_writes, &blk)
150
+ end
151
+
152
+ # Connects a role and/or shard to the provided connection names. Optionally +prevent_writes+
153
+ # can be passed to block writes on a connection. +reading+ will automatically set
154
+ # +prevent_writes+ to true.
155
+ #
156
+ # +connected_to_many+ is an alternative to deeply nested +connected_to+ blocks.
157
+ #
158
+ # Usage:
159
+ #
160
+ # ActiveRecord::Base.connected_to_many(AnimalsRecord, MealsRecord, role: :reading) do
161
+ # Dog.first # Read from animals replica
162
+ # Dinner.first # Read from meals replica
163
+ # Person.first # Read from primary writer
164
+ # end
165
+ def connected_to_many(*classes, role:, shard: nil, prevent_writes: false)
166
+ classes = classes.flatten
167
+
168
+ if self != Base || classes.include?(Base)
169
+ raise NotImplementedError, "connected_to_many can only be called on ActiveRecord::Base."
170
+ end
171
+
172
+ prevent_writes = true if role == ActiveRecord.reading_role
173
+
174
+ append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: classes)
175
+ yield
176
+ ensure
177
+ connected_to_stack.pop
178
+ end
179
+
180
+ # Passes the block to +connected_to+ for every +shard+ the
181
+ # model is configured to connect to (if any), and returns the
182
+ # results in an array.
183
+ #
184
+ # Optionally, +role+ and/or +prevent_writes+ can be passed which
185
+ # will be forwarded to each +connected_to+ call.
186
+ def connected_to_all_shards(role: nil, prevent_writes: false, &blk)
187
+ shard_keys.map do |shard|
188
+ connected_to(shard: shard, role: role, prevent_writes: prevent_writes, &blk)
189
+ end
190
+ end
191
+
192
+ # Use a specified connection.
193
+ #
194
+ # This method is useful for ensuring that a specific connection is
195
+ # being used. For example, when booting a console in readonly mode.
196
+ #
197
+ # It is not recommended to use this method in a request since it
198
+ # does not yield to a block like +connected_to+.
199
+ def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
200
+ prevent_writes = true if role == ActiveRecord.reading_role
201
+
202
+ append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
203
+ end
204
+
205
+ # Prohibit swapping shards while inside of the passed block.
206
+ #
207
+ # In some cases you may want to be able to swap shards but not allow a
208
+ # nested call to connected_to or connected_to_many to swap again. This
209
+ # is useful in cases you're using sharding to provide per-request
210
+ # database isolation.
211
+ def prohibit_shard_swapping(enabled = true)
212
+ prev_value = ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping]
213
+ ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = enabled
214
+ yield
215
+ ensure
216
+ ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = prev_value
217
+ end
218
+
219
+ # Determine whether or not shard swapping is currently prohibited
220
+ def shard_swapping_prohibited?
221
+ ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping]
222
+ end
223
+
224
+ # Prevent writing to the database regardless of role.
225
+ #
226
+ # In some cases you may want to prevent writes to the database
227
+ # even if you are on a database that can write. +while_preventing_writes+
228
+ # will prevent writes to the database for the duration of the block.
229
+ #
230
+ # This method does not provide the same protection as a readonly
231
+ # user and is meant to be a safeguard against accidental writes.
232
+ #
233
+ # See +READ_QUERY+ for the queries that are blocked by this
234
+ # method.
235
+ def while_preventing_writes(enabled = true, &block)
236
+ connected_to(role: current_role, prevent_writes: enabled, &block)
237
+ end
238
+
239
+ # Returns true if role is the current connected role and/or
240
+ # current connected shard. If no shard is passed, the default will be
241
+ # used.
242
+ #
243
+ # ActiveRecord::Base.connected_to(role: :writing) do
244
+ # ActiveRecord::Base.connected_to?(role: :writing) #=> true
245
+ # ActiveRecord::Base.connected_to?(role: :reading) #=> false
246
+ # end
247
+ #
248
+ # ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one) do
249
+ # ActiveRecord::Base.connected_to?(role: :reading, shard: :shard_one) #=> true
250
+ # ActiveRecord::Base.connected_to?(role: :reading, shard: :default) #=> false
251
+ # ActiveRecord::Base.connected_to?(role: :writing, shard: :shard_one) #=> true
252
+ # end
253
+ def connected_to?(role:, shard: ActiveRecord::Base.default_shard)
254
+ current_role == role.to_sym && current_shard == shard.to_sym
255
+ end
256
+
257
+ # Clears the query cache for all connections associated with the current thread.
258
+ def clear_query_caches_for_current_thread
259
+ connection_handler.each_connection_pool do |pool|
260
+ pool.clear_query_cache
261
+ end
262
+ end
263
+
264
+ # Returns the connection currently associated with the class. This can
265
+ # also be used to "borrow" the connection to do database work unrelated
266
+ # to any of the specific Active Records.
267
+ # The connection will remain leased for the entire duration of the request
268
+ # or job, or until +#release_connection+ is called.
269
+ def lease_connection
270
+ connection_pool.lease_connection
271
+ end
272
+
273
+ # Soft deprecated. Use +#with_connection+ or +#lease_connection+ instead.
274
+ def connection
275
+ pool = connection_pool
276
+ if pool.permanent_lease?
277
+ case ActiveRecord.permanent_connection_checkout
278
+ when :deprecated
279
+ ActiveRecord.deprecator.warn <<~MESSAGE
280
+ Called deprecated `ActiveRecord::Base.connection` method.
281
+
282
+ Either use `with_connection` or `lease_connection`.
283
+ MESSAGE
284
+ when :disallowed
285
+ raise ActiveRecordError, <<~MESSAGE
286
+ Called deprecated `ActiveRecord::Base.connection` method.
287
+
288
+ Either use `with_connection` or `lease_connection`.
289
+ MESSAGE
290
+ end
291
+ pool.lease_connection
292
+ else
293
+ pool.active_connection
294
+ end
295
+ end
296
+
297
+ # Return the currently leased connection into the pool
298
+ def release_connection
299
+ connection_pool.release_connection
300
+ end
301
+
302
+ # Checkouts a connection from the pool, yield it and then check it back in.
303
+ # If a connection was already leased via #lease_connection or a parent call to
304
+ # #with_connection, that same connection is yieled.
305
+ # If #lease_connection is called inside the block, the connection won't be checked
306
+ # back in.
307
+ # If #connection is called inside the block, the connection won't be checked back in
308
+ # unless the +prevent_permanent_checkout+ argument is set to +true+.
309
+ def with_connection(prevent_permanent_checkout: false, &block)
310
+ connection_pool.with_connection(prevent_permanent_checkout: prevent_permanent_checkout, &block)
311
+ end
312
+
313
+ attr_writer :connection_specification_name
314
+
315
+ # Returns the connection specification name from the current class or its parent.
316
+ def connection_specification_name
317
+ if @connection_specification_name.nil?
318
+ return self == Base ? Base.name : superclass.connection_specification_name
319
+ end
320
+ @connection_specification_name
321
+ end
322
+
323
+ def primary_class? # :nodoc:
324
+ self == Base || application_record_class?
325
+ end
326
+
327
+ # Returns the db_config object from the associated connection:
328
+ #
329
+ # ActiveRecord::Base.connection_db_config
330
+ # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
331
+ # @name="primary", @config={pool: 5, timeout: 5000, database: "storage/development.sqlite3", adapter: "sqlite3"}>
332
+ #
333
+ # Use only for reading.
334
+ def connection_db_config
335
+ connection_pool.db_config
336
+ end
337
+
338
+ def adapter_class # :nodoc:
339
+ connection_pool.db_config.adapter_class
340
+ end
341
+
342
+ def connection_pool
343
+ connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard, strict: true)
344
+ end
345
+
346
+ def retrieve_connection
347
+ connection_handler.retrieve_connection(connection_specification_name, role: current_role, shard: current_shard)
348
+ end
349
+
350
+ # Returns +true+ if Active Record is connected.
351
+ def connected?
352
+ connection_handler.connected?(connection_specification_name, role: current_role, shard: current_shard)
353
+ end
354
+
355
+ def remove_connection
356
+ name = @connection_specification_name if defined?(@connection_specification_name)
357
+
358
+ # if removing a connection that has a pool, we reset the
359
+ # connection_specification_name so it will use the parent
360
+ # pool.
361
+ if connection_handler.retrieve_connection_pool(name, role: current_role, shard: current_shard)
362
+ self.connection_specification_name = nil
363
+ end
364
+
365
+ connection_handler.remove_connection_pool(name, role: current_role, shard: current_shard)
366
+ end
367
+
368
+ def schema_cache # :nodoc:
369
+ connection_pool.schema_cache
370
+ end
371
+
372
+ def clear_cache! # :nodoc:
373
+ connection_pool.schema_cache.clear!
374
+ end
375
+
376
+ def shard_keys
377
+ connection_class_for_self.instance_variable_get(:@shard_keys) || []
378
+ end
379
+
380
+ def sharded?
381
+ shard_keys.any?
382
+ end
383
+
384
+ private
385
+ def resolve_config_for_connection(config_or_env)
386
+ raise "Anonymous class is not allowed." unless name
387
+
388
+ connection_name = primary_class? ? Base.name : name
389
+ self.connection_specification_name = connection_name
390
+
391
+ Base.configurations.resolve(config_or_env)
392
+ end
393
+
394
+ def with_role_and_shard(role, shard, prevent_writes)
395
+ prevent_writes = true if role == ActiveRecord.reading_role
396
+
397
+ append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
398
+ return_value = yield
399
+ return_value.load if return_value.is_a? ActiveRecord::Relation
400
+ return_value
401
+ ensure
402
+ self.connected_to_stack.pop
403
+ end
404
+
405
+ def append_to_connected_to_stack(entry)
406
+ if shard_swapping_prohibited? && entry[:shard].present?
407
+ raise ArgumentError, "cannot swap `shard` while shard swapping is prohibited."
408
+ end
409
+
410
+ connected_to_stack << entry
411
+ end
412
+ end
413
+ end