activerecord 6.0.0 → 7.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +996 -594
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +34 -34
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +22 -20
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +41 -30
  9. data/lib/active_record/associations/association.rb +106 -41
  10. data/lib/active_record/associations/association_scope.rb +30 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +69 -14
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
  13. data/lib/active_record/associations/builder/association.rb +39 -6
  14. data/lib/active_record/associations/builder/belongs_to.rb +47 -17
  15. data/lib/active_record/associations/builder/collection_association.rb +14 -6
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
  17. data/lib/active_record/associations/builder/has_many.rb +7 -3
  18. data/lib/active_record/associations/builder/has_one.rb +13 -16
  19. data/lib/active_record/associations/builder/singular_association.rb +7 -3
  20. data/lib/active_record/associations/collection_association.rb +90 -53
  21. data/lib/active_record/associations/collection_proxy.rb +54 -19
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/errors.rb +265 -0
  24. data/lib/active_record/associations/foreign_association.rb +21 -1
  25. data/lib/active_record/associations/has_many_association.rb +41 -10
  26. data/lib/active_record/associations/has_many_through_association.rb +29 -12
  27. data/lib/active_record/associations/has_one_association.rb +33 -9
  28. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  29. data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
  30. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  31. data/lib/active_record/associations/join_dependency.rb +97 -54
  32. data/lib/active_record/associations/nested_error.rb +47 -0
  33. data/lib/active_record/associations/preloader/association.rb +237 -54
  34. data/lib/active_record/associations/preloader/batch.rb +48 -0
  35. data/lib/active_record/associations/preloader/branch.rb +153 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +51 -17
  37. data/lib/active_record/associations/preloader.rb +55 -121
  38. data/lib/active_record/associations/singular_association.rb +16 -4
  39. data/lib/active_record/associations/through_association.rb +26 -15
  40. data/lib/active_record/associations.rb +454 -440
  41. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  42. data/lib/active_record/attribute_assignment.rb +11 -14
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
  44. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  45. data/lib/active_record/attribute_methods/dirty.rb +75 -34
  46. data/lib/active_record/attribute_methods/primary_key.rb +53 -31
  47. data/lib/active_record/attribute_methods/query.rb +31 -22
  48. data/lib/active_record/attribute_methods/read.rb +16 -17
  49. data/lib/active_record/attribute_methods/serialization.rb +177 -35
  50. data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
  51. data/lib/active_record/attribute_methods/write.rb +16 -28
  52. data/lib/active_record/attribute_methods.rb +227 -100
  53. data/lib/active_record/attributes.rb +94 -56
  54. data/lib/active_record/autosave_association.rb +119 -73
  55. data/lib/active_record/base.rb +31 -21
  56. data/lib/active_record/callbacks.rb +168 -55
  57. data/lib/active_record/coders/column_serializer.rb +61 -0
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +70 -25
  60. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +367 -565
  64. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
  65. data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
  66. data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
  67. data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
  68. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  69. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  70. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
  71. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
  72. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
  73. data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
  74. data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
  75. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
  76. data/lib/active_record/connection_adapters/column.rb +28 -1
  77. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  78. data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
  79. data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
  80. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  81. data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
  82. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
  83. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
  84. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
  85. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
  86. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  87. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  88. data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
  89. data/lib/active_record/connection_adapters/pool_config.rb +83 -0
  90. data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
  91. data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
  92. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
  95. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
  97. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  101. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
  106. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  110. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -4
  111. data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
  121. data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
  123. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  124. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +102 -24
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
  131. data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
  132. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  133. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  134. data/lib/active_record/connection_adapters.rb +176 -0
  135. data/lib/active_record/connection_handling.rb +243 -115
  136. data/lib/active_record/core.rb +481 -199
  137. data/lib/active_record/counter_cache.rb +69 -32
  138. data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
  139. data/lib/active_record/database_configurations/database_config.rb +77 -10
  140. data/lib/active_record/database_configurations/hash_config.rb +148 -26
  141. data/lib/active_record/database_configurations/url_config.rb +44 -45
  142. data/lib/active_record/database_configurations.rb +190 -114
  143. data/lib/active_record/delegated_type.rb +279 -0
  144. data/lib/active_record/deprecator.rb +7 -0
  145. data/lib/active_record/destroy_association_async_job.rb +38 -0
  146. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  147. data/lib/active_record/dynamic_matchers.rb +5 -6
  148. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  149. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  150. data/lib/active_record/encryption/cipher.rb +53 -0
  151. data/lib/active_record/encryption/config.rb +68 -0
  152. data/lib/active_record/encryption/configurable.rb +60 -0
  153. data/lib/active_record/encryption/context.rb +42 -0
  154. data/lib/active_record/encryption/contexts.rb +76 -0
  155. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  156. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  157. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  158. data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
  159. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  160. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  161. data/lib/active_record/encryption/encryptor.rb +171 -0
  162. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  163. data/lib/active_record/encryption/errors.rb +15 -0
  164. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  165. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  166. data/lib/active_record/encryption/key.rb +28 -0
  167. data/lib/active_record/encryption/key_generator.rb +53 -0
  168. data/lib/active_record/encryption/key_provider.rb +46 -0
  169. data/lib/active_record/encryption/message.rb +33 -0
  170. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  171. data/lib/active_record/encryption/message_serializer.rb +96 -0
  172. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  173. data/lib/active_record/encryption/properties.rb +76 -0
  174. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  175. data/lib/active_record/encryption/scheme.rb +100 -0
  176. data/lib/active_record/encryption.rb +58 -0
  177. data/lib/active_record/enum.rb +224 -73
  178. data/lib/active_record/errors.rb +254 -36
  179. data/lib/active_record/explain.rb +30 -17
  180. data/lib/active_record/explain_registry.rb +11 -6
  181. data/lib/active_record/explain_subscriber.rb +2 -2
  182. data/lib/active_record/fixture_set/file.rb +22 -15
  183. data/lib/active_record/fixture_set/model_metadata.rb +15 -6
  184. data/lib/active_record/fixture_set/render_context.rb +3 -1
  185. data/lib/active_record/fixture_set/table_row.rb +88 -16
  186. data/lib/active_record/fixture_set/table_rows.rb +4 -5
  187. data/lib/active_record/fixtures.rb +229 -116
  188. data/lib/active_record/future_result.rb +178 -0
  189. data/lib/active_record/gem_version.rb +4 -4
  190. data/lib/active_record/inheritance.rb +121 -48
  191. data/lib/active_record/insert_all.rb +178 -29
  192. data/lib/active_record/integration.rb +16 -14
  193. data/lib/active_record/internal_metadata.rb +132 -21
  194. data/lib/active_record/legacy_yaml_adapter.rb +3 -36
  195. data/lib/active_record/locking/optimistic.rb +64 -33
  196. data/lib/active_record/locking/pessimistic.rb +21 -8
  197. data/lib/active_record/log_subscriber.rb +61 -30
  198. data/lib/active_record/marshalling.rb +59 -0
  199. data/lib/active_record/message_pack.rb +124 -0
  200. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  201. data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
  202. data/lib/active_record/middleware/database_selector.rb +25 -13
  203. data/lib/active_record/middleware/shard_selector.rb +62 -0
  204. data/lib/active_record/migration/command_recorder.rb +160 -55
  205. data/lib/active_record/migration/compatibility.rb +286 -43
  206. data/lib/active_record/migration/default_strategy.rb +22 -0
  207. data/lib/active_record/migration/execution_strategy.rb +19 -0
  208. data/lib/active_record/migration/join_table.rb +1 -2
  209. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  210. data/lib/active_record/migration.rb +421 -193
  211. data/lib/active_record/model_schema.rb +217 -125
  212. data/lib/active_record/nested_attributes.rb +62 -27
  213. data/lib/active_record/no_touching.rb +4 -4
  214. data/lib/active_record/normalization.rb +163 -0
  215. data/lib/active_record/persistence.rb +322 -319
  216. data/lib/active_record/promise.rb +84 -0
  217. data/lib/active_record/query_cache.rb +18 -15
  218. data/lib/active_record/query_logs.rb +193 -0
  219. data/lib/active_record/query_logs_formatter.rb +41 -0
  220. data/lib/active_record/querying.rb +54 -14
  221. data/lib/active_record/railtie.rb +250 -72
  222. data/lib/active_record/railties/console_sandbox.rb +2 -4
  223. data/lib/active_record/railties/controller_runtime.rb +25 -11
  224. data/lib/active_record/railties/databases.rake +312 -197
  225. data/lib/active_record/railties/job_runtime.rb +23 -0
  226. data/lib/active_record/readonly_attributes.rb +45 -3
  227. data/lib/active_record/reflection.rb +389 -146
  228. data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
  229. data/lib/active_record/relation/batches.rb +214 -73
  230. data/lib/active_record/relation/calculations.rb +379 -124
  231. data/lib/active_record/relation/delegation.rb +36 -23
  232. data/lib/active_record/relation/finder_methods.rb +159 -49
  233. data/lib/active_record/relation/from_clause.rb +5 -1
  234. data/lib/active_record/relation/merger.rb +41 -33
  235. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
  236. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
  237. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
  238. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  239. data/lib/active_record/relation/predicate_builder.rb +79 -53
  240. data/lib/active_record/relation/query_attribute.rb +30 -12
  241. data/lib/active_record/relation/query_methods.rb +1156 -279
  242. data/lib/active_record/relation/record_fetch_warning.rb +12 -11
  243. data/lib/active_record/relation/spawn_methods.rb +10 -9
  244. data/lib/active_record/relation/where_clause.rb +100 -66
  245. data/lib/active_record/relation.rb +829 -194
  246. data/lib/active_record/result.rb +76 -56
  247. data/lib/active_record/runtime_registry.rb +71 -13
  248. data/lib/active_record/sanitization.rb +86 -47
  249. data/lib/active_record/schema.rb +39 -23
  250. data/lib/active_record/schema_dumper.rb +140 -33
  251. data/lib/active_record/schema_migration.rb +74 -29
  252. data/lib/active_record/scoping/default.rb +73 -19
  253. data/lib/active_record/scoping/named.rb +10 -28
  254. data/lib/active_record/scoping.rb +65 -35
  255. data/lib/active_record/secure_password.rb +60 -0
  256. data/lib/active_record/secure_token.rb +34 -8
  257. data/lib/active_record/serialization.rb +11 -4
  258. data/lib/active_record/signed_id.rb +138 -0
  259. data/lib/active_record/statement_cache.rb +26 -10
  260. data/lib/active_record/store.rb +19 -14
  261. data/lib/active_record/suppressor.rb +15 -17
  262. data/lib/active_record/table_metadata.rb +46 -36
  263. data/lib/active_record/tasks/database_tasks.rb +371 -205
  264. data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
  265. data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
  266. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
  267. data/lib/active_record/test_databases.rb +5 -4
  268. data/lib/active_record/test_fixtures.rb +189 -104
  269. data/lib/active_record/testing/query_assertions.rb +121 -0
  270. data/lib/active_record/timestamp.rb +35 -25
  271. data/lib/active_record/token_for.rb +123 -0
  272. data/lib/active_record/touch_later.rb +31 -27
  273. data/lib/active_record/transaction.rb +132 -0
  274. data/lib/active_record/transactions.rb +131 -99
  275. data/lib/active_record/translation.rb +3 -5
  276. data/lib/active_record/type/adapter_specific_registry.rb +33 -18
  277. data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
  278. data/lib/active_record/type/internal/timezone.rb +7 -2
  279. data/lib/active_record/type/serialized.rb +11 -6
  280. data/lib/active_record/type/time.rb +14 -0
  281. data/lib/active_record/type/type_map.rb +17 -21
  282. data/lib/active_record/type/unsigned_integer.rb +0 -1
  283. data/lib/active_record/type.rb +7 -2
  284. data/lib/active_record/type_caster/connection.rb +4 -5
  285. data/lib/active_record/type_caster/map.rb +8 -5
  286. data/lib/active_record/validations/absence.rb +1 -1
  287. data/lib/active_record/validations/associated.rb +13 -8
  288. data/lib/active_record/validations/numericality.rb +36 -0
  289. data/lib/active_record/validations/presence.rb +5 -28
  290. data/lib/active_record/validations/uniqueness.rb +88 -18
  291. data/lib/active_record/validations.rb +15 -8
  292. data/lib/active_record/version.rb +1 -1
  293. data/lib/active_record.rb +446 -40
  294. data/lib/arel/alias_predication.rb +1 -1
  295. data/lib/arel/attributes/attribute.rb +4 -8
  296. data/lib/arel/collectors/bind.rb +8 -1
  297. data/lib/arel/collectors/composite.rb +15 -0
  298. data/lib/arel/collectors/sql_string.rb +7 -0
  299. data/lib/arel/collectors/substitute_binds.rb +7 -0
  300. data/lib/arel/crud.rb +30 -22
  301. data/lib/arel/delete_manager.rb +23 -4
  302. data/lib/arel/errors.rb +10 -0
  303. data/lib/arel/factory_methods.rb +4 -0
  304. data/lib/arel/filter_predications.rb +9 -0
  305. data/lib/arel/insert_manager.rb +2 -3
  306. data/lib/arel/nodes/binary.rb +82 -9
  307. data/lib/arel/nodes/bind_param.rb +8 -0
  308. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  309. data/lib/arel/nodes/casted.rb +22 -10
  310. data/lib/arel/nodes/cte.rb +36 -0
  311. data/lib/arel/nodes/delete_statement.rb +14 -13
  312. data/lib/arel/nodes/equality.rb +6 -9
  313. data/lib/arel/nodes/filter.rb +10 -0
  314. data/lib/arel/nodes/fragments.rb +35 -0
  315. data/lib/arel/nodes/function.rb +1 -0
  316. data/lib/arel/nodes/grouping.rb +3 -0
  317. data/lib/arel/nodes/homogeneous_in.rb +68 -0
  318. data/lib/arel/nodes/in.rb +8 -1
  319. data/lib/arel/nodes/infix_operation.rb +13 -1
  320. data/lib/arel/nodes/insert_statement.rb +2 -2
  321. data/lib/arel/nodes/join_source.rb +1 -1
  322. data/lib/arel/nodes/leading_join.rb +8 -0
  323. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  324. data/lib/arel/nodes/node.rb +122 -11
  325. data/lib/arel/nodes/ordering.rb +27 -0
  326. data/lib/arel/nodes/select_core.rb +2 -2
  327. data/lib/arel/nodes/select_statement.rb +2 -2
  328. data/lib/arel/nodes/sql_literal.rb +16 -0
  329. data/lib/arel/nodes/table_alias.rb +11 -3
  330. data/lib/arel/nodes/unary.rb +0 -1
  331. data/lib/arel/nodes/update_statement.rb +11 -4
  332. data/lib/arel/nodes.rb +10 -3
  333. data/lib/arel/predications.rb +31 -28
  334. data/lib/arel/select_manager.rb +18 -9
  335. data/lib/arel/table.rb +21 -10
  336. data/lib/arel/tree_manager.rb +8 -15
  337. data/lib/arel/update_manager.rb +25 -5
  338. data/lib/arel/visitors/dot.rb +94 -90
  339. data/lib/arel/visitors/mysql.rb +34 -6
  340. data/lib/arel/visitors/postgresql.rb +5 -16
  341. data/lib/arel/visitors/sqlite.rb +25 -1
  342. data/lib/arel/visitors/to_sql.rb +227 -81
  343. data/lib/arel/visitors/visitor.rb +2 -3
  344. data/lib/arel/visitors.rb +0 -7
  345. data/lib/arel.rb +37 -15
  346. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  347. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  348. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  349. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  350. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
  351. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  352. data/lib/rails/generators/active_record/migration.rb +9 -3
  353. data/lib/rails/generators/active_record/model/USAGE +113 -0
  354. data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
  355. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  356. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  357. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  358. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  359. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  360. metadata +117 -30
  361. data/lib/active_record/attribute_decorators.rb +0 -90
  362. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  363. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  364. data/lib/active_record/define_callbacks.rb +0 -22
  365. data/lib/active_record/null_relation.rb +0 -68
  366. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  367. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  368. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  369. data/lib/arel/attributes.rb +0 -22
  370. data/lib/arel/visitors/depth_first.rb +0 -204
  371. data/lib/arel/visitors/ibm_db.rb +0 -34
  372. data/lib/arel/visitors/informix.rb +0 -62
  373. data/lib/arel/visitors/mssql.rb +0 -157
  374. data/lib/arel/visitors/oracle.rb +0 -159
  375. data/lib/arel/visitors/oracle12.rb +0 -66
  376. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -5,32 +5,30 @@ module ActiveRecord
5
5
  class MySQLDatabaseTasks # :nodoc:
6
6
  ER_DB_CREATE_EXISTS = 1007
7
7
 
8
- delegate :connection, :establish_connection, to: ActiveRecord::Base
8
+ def self.using_database_configurations?
9
+ true
10
+ end
9
11
 
10
- def initialize(configuration)
11
- @configuration = configuration
12
+ def initialize(db_config)
13
+ @db_config = db_config
14
+ @configuration_hash = db_config.configuration_hash
12
15
  end
13
16
 
14
17
  def create
15
- establish_connection configuration_without_database
16
- connection.create_database configuration["database"], creation_options
17
- establish_connection configuration
18
- rescue ActiveRecord::StatementInvalid => error
19
- if connection.error_number(error.cause) == ER_DB_CREATE_EXISTS
20
- raise DatabaseAlreadyExists
21
- else
22
- raise
23
- end
18
+ establish_connection(configuration_hash_without_database)
19
+ connection.create_database(db_config.database, creation_options)
20
+ establish_connection
24
21
  end
25
22
 
26
23
  def drop
27
- establish_connection configuration
28
- connection.drop_database configuration["database"]
24
+ establish_connection
25
+ connection.drop_database(db_config.database)
29
26
  end
30
27
 
31
28
  def purge
32
- establish_connection configuration
33
- connection.recreate_database configuration["database"], creation_options
29
+ establish_connection(configuration_hash_without_database)
30
+ connection.recreate_database(db_config.database, creation_options)
31
+ establish_connection
34
32
  end
35
33
 
36
34
  def charset
@@ -50,10 +48,11 @@ module ActiveRecord
50
48
 
51
49
  ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
52
50
  if ignore_tables.any?
53
- args += ignore_tables.map { |table| "--ignore-table=#{configuration['database']}.#{table}" }
51
+ ignore_tables = connection.data_sources.select { |table| ignore_tables.any? { |pattern| pattern === table } }
52
+ args += ignore_tables.map { |table| "--ignore-table=#{db_config.database}.#{table}" }
54
53
  end
55
54
 
56
- args.concat(["#{configuration['database']}"])
55
+ args.concat([db_config.database.to_s])
57
56
  args.unshift(*extra_flags) if extra_flags
58
57
 
59
58
  run_cmd("mysqldump", args, "dumping")
@@ -62,41 +61,49 @@ module ActiveRecord
62
61
  def structure_load(filename, extra_flags)
63
62
  args = prepare_command_options
64
63
  args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
65
- args.concat(["--database", "#{configuration['database']}"])
64
+ args.concat(["--database", db_config.database.to_s])
66
65
  args.unshift(*extra_flags) if extra_flags
67
66
 
68
67
  run_cmd("mysql", args, "loading")
69
68
  end
70
69
 
71
70
  private
71
+ attr_reader :db_config, :configuration_hash
72
72
 
73
- attr_reader :configuration
73
+ def connection
74
+ ActiveRecord::Base.lease_connection
75
+ end
76
+
77
+ def establish_connection(config = db_config)
78
+ ActiveRecord::Base.establish_connection(config)
79
+ end
74
80
 
75
- def configuration_without_database
76
- configuration.merge("database" => nil)
81
+ def configuration_hash_without_database
82
+ configuration_hash.merge(database: nil)
77
83
  end
78
84
 
79
85
  def creation_options
80
86
  Hash.new.tap do |options|
81
- options[:charset] = configuration["encoding"] if configuration.include? "encoding"
82
- options[:collation] = configuration["collation"] if configuration.include? "collation"
87
+ options[:charset] = configuration_hash[:encoding] if configuration_hash.include?(:encoding)
88
+ options[:collation] = configuration_hash[:collation] if configuration_hash.include?(:collation)
83
89
  end
84
90
  end
85
91
 
86
92
  def prepare_command_options
87
93
  args = {
88
- "host" => "--host",
89
- "port" => "--port",
90
- "socket" => "--socket",
91
- "username" => "--user",
92
- "password" => "--password",
93
- "encoding" => "--default-character-set",
94
- "sslca" => "--ssl-ca",
95
- "sslcert" => "--ssl-cert",
96
- "sslcapath" => "--ssl-capath",
97
- "sslcipher" => "--ssl-cipher",
98
- "sslkey" => "--ssl-key"
99
- }.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
94
+ host: "--host",
95
+ port: "--port",
96
+ socket: "--socket",
97
+ username: "--user",
98
+ password: "--password",
99
+ encoding: "--default-character-set",
100
+ sslca: "--ssl-ca",
101
+ sslcert: "--ssl-cert",
102
+ sslcapath: "--ssl-capath",
103
+ sslcipher: "--ssl-cipher",
104
+ sslkey: "--ssl-key",
105
+ ssl_mode: "--ssl-mode"
106
+ }.filter_map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }
100
107
 
101
108
  args
102
109
  end
@@ -9,29 +9,24 @@ module ActiveRecord
9
9
  ON_ERROR_STOP_1 = "ON_ERROR_STOP=1"
10
10
  SQL_COMMENT_BEGIN = "--"
11
11
 
12
- delegate :connection, :establish_connection, :clear_active_connections!,
13
- to: ActiveRecord::Base
12
+ def self.using_database_configurations?
13
+ true
14
+ end
14
15
 
15
- def initialize(configuration)
16
- @configuration = configuration
16
+ def initialize(db_config)
17
+ @db_config = db_config
18
+ @configuration_hash = db_config.configuration_hash
17
19
  end
18
20
 
19
- def create(master_established = false)
20
- establish_master_connection unless master_established
21
- connection.create_database configuration["database"],
22
- configuration.merge("encoding" => encoding)
23
- establish_connection configuration
24
- rescue ActiveRecord::StatementInvalid => error
25
- if error.cause.is_a?(PG::DuplicateDatabase)
26
- raise DatabaseAlreadyExists
27
- else
28
- raise
29
- end
21
+ def create(connection_already_established = false)
22
+ establish_connection(public_schema_config) unless connection_already_established
23
+ connection.create_database(db_config.database, configuration_hash.merge(encoding: encoding))
24
+ establish_connection
30
25
  end
31
26
 
32
27
  def drop
33
- establish_master_connection
34
- connection.drop_database configuration["database"]
28
+ establish_connection(public_schema_config)
29
+ connection.drop_database(db_config.database)
35
30
  end
36
31
 
37
32
  def charset
@@ -43,26 +38,27 @@ module ActiveRecord
43
38
  end
44
39
 
45
40
  def purge
46
- clear_active_connections!
41
+ ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
47
42
  drop
48
43
  create true
49
44
  end
50
45
 
51
46
  def structure_dump(filename, extra_flags)
52
- set_psql_env
53
-
54
47
  search_path = \
55
- case ActiveRecord::Base.dump_schemas
48
+ case ActiveRecord.dump_schemas
56
49
  when :schema_search_path
57
- configuration["schema_search_path"]
50
+ configuration_hash[:schema_search_path]
58
51
  when :all
59
52
  nil
60
53
  when String
61
- ActiveRecord::Base.dump_schemas
54
+ ActiveRecord.dump_schemas
62
55
  end
63
56
 
64
- args = ["-s", "-x", "-O", "-f", filename]
57
+ args = ["--schema-only", "--no-privileges", "--no-owner"]
58
+ args.concat(["--file", filename])
59
+
65
60
  args.concat(Array(extra_flags)) if extra_flags
61
+
66
62
  unless search_path.blank?
67
63
  args += search_path.split(",").map do |part|
68
64
  "--schema=#{part.strip}"
@@ -71,47 +67,57 @@ module ActiveRecord
71
67
 
72
68
  ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
73
69
  if ignore_tables.any?
70
+ ignore_tables = connection.data_sources.select { |table| ignore_tables.any? { |pattern| pattern === table } }
74
71
  args += ignore_tables.flat_map { |table| ["-T", table] }
75
72
  end
76
73
 
77
- args << configuration["database"]
74
+ args << db_config.database
78
75
  run_cmd("pg_dump", args, "dumping")
79
76
  remove_sql_header_comments(filename)
80
77
  File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
81
78
  end
82
79
 
83
80
  def structure_load(filename, extra_flags)
84
- set_psql_env
85
- args = ["-v", ON_ERROR_STOP_1, "-q", "-X", "-f", filename]
81
+ args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--output", File::NULL, "--file", filename]
86
82
  args.concat(Array(extra_flags)) if extra_flags
87
- args << configuration["database"]
83
+ args << db_config.database
88
84
  run_cmd("psql", args, "loading")
89
85
  end
90
86
 
91
87
  private
88
+ attr_reader :db_config, :configuration_hash
89
+
90
+ def connection
91
+ ActiveRecord::Base.lease_connection
92
+ end
92
93
 
93
- attr_reader :configuration
94
+ def establish_connection(config = db_config)
95
+ ActiveRecord::Base.establish_connection(config)
96
+ end
94
97
 
95
98
  def encoding
96
- configuration["encoding"] || DEFAULT_ENCODING
99
+ configuration_hash[:encoding] || DEFAULT_ENCODING
97
100
  end
98
101
 
99
- def establish_master_connection
100
- establish_connection configuration.merge(
101
- "database" => "postgres",
102
- "schema_search_path" => "public"
103
- )
102
+ def public_schema_config
103
+ configuration_hash.merge(database: "postgres", schema_search_path: "public")
104
104
  end
105
105
 
106
- def set_psql_env
107
- ENV["PGHOST"] = configuration["host"] if configuration["host"]
108
- ENV["PGPORT"] = configuration["port"].to_s if configuration["port"]
109
- ENV["PGPASSWORD"] = configuration["password"].to_s if configuration["password"]
110
- ENV["PGUSER"] = configuration["username"].to_s if configuration["username"]
106
+ def psql_env
107
+ {}.tap do |env|
108
+ env["PGHOST"] = db_config.host if db_config.host
109
+ env["PGPORT"] = configuration_hash[:port].to_s if configuration_hash[:port]
110
+ env["PGPASSWORD"] = configuration_hash[:password].to_s if configuration_hash[:password]
111
+ env["PGUSER"] = configuration_hash[:username].to_s if configuration_hash[:username]
112
+ env["PGSSLMODE"] = configuration_hash[:sslmode].to_s if configuration_hash[:sslmode]
113
+ env["PGSSLCERT"] = configuration_hash[:sslcert].to_s if configuration_hash[:sslcert]
114
+ env["PGSSLKEY"] = configuration_hash[:sslkey].to_s if configuration_hash[:sslkey]
115
+ env["PGSSLROOTCERT"] = configuration_hash[:sslrootcert].to_s if configuration_hash[:sslrootcert]
116
+ end
111
117
  end
112
118
 
113
119
  def run_cmd(cmd, args, action)
114
- fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
120
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(psql_env, cmd, *args)
115
121
  end
116
122
 
117
123
  def run_cmd_error(cmd, args, action)
@@ -126,6 +132,13 @@ module ActiveRecord
126
132
  tempfile = Tempfile.open("uncommented_structure.sql")
127
133
  begin
128
134
  File.foreach(filename) do |line|
135
+ next if line.start_with?("\\restrict ")
136
+
137
+ if line.start_with?("\\unrestrict ")
138
+ removing_comments = true
139
+ next
140
+ end
141
+
129
142
  unless removing_comments && (line.start_with?(SQL_COMMENT_BEGIN) || line.blank?)
130
143
  tempfile << line
131
144
  removing_comments = false
@@ -3,34 +3,38 @@
3
3
  module ActiveRecord
4
4
  module Tasks # :nodoc:
5
5
  class SQLiteDatabaseTasks # :nodoc:
6
- delegate :connection, :establish_connection, to: ActiveRecord::Base
6
+ def self.using_database_configurations?
7
+ true
8
+ end
7
9
 
8
- def initialize(configuration, root = ActiveRecord::Tasks::DatabaseTasks.root)
9
- @configuration, @root = configuration, root
10
+ def initialize(db_config, root = ActiveRecord::Tasks::DatabaseTasks.root)
11
+ @db_config = db_config
12
+ @root = root
10
13
  end
11
14
 
12
15
  def create
13
- raise DatabaseAlreadyExists if File.exist?(configuration["database"])
16
+ raise DatabaseAlreadyExists if File.exist?(db_config.database)
14
17
 
15
- establish_connection configuration
18
+ establish_connection
16
19
  connection
17
20
  end
18
21
 
19
22
  def drop
20
- require "pathname"
21
- path = Pathname.new configuration["database"]
22
- file = path.absolute? ? path.to_s : File.join(root, path)
23
-
23
+ db_path = db_config.database
24
+ file = File.absolute_path?(db_path) ? db_path : File.join(root, db_path)
24
25
  FileUtils.rm(file)
26
+ FileUtils.rm_f(["#{file}-shm", "#{file}-wal"])
25
27
  rescue Errno::ENOENT => error
26
28
  raise NoDatabaseError.new(error.message)
27
29
  end
28
30
 
29
31
  def purge
32
+ connection.disconnect!
30
33
  drop
31
34
  rescue NoDatabaseError
32
35
  ensure
33
36
  create
37
+ connection.reconnect!
34
38
  end
35
39
 
36
40
  def charset
@@ -40,10 +44,11 @@ module ActiveRecord
40
44
  def structure_dump(filename, extra_flags)
41
45
  args = []
42
46
  args.concat(Array(extra_flags)) if extra_flags
43
- args << configuration["database"]
47
+ args << db_config.database
44
48
 
45
49
  ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
46
50
  if ignore_tables.any?
51
+ ignore_tables = connection.data_sources.select { |table| ignore_tables.any? { |pattern| pattern === table } }
47
52
  condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
48
53
  args << "SELECT sql FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
49
54
  else
@@ -53,14 +58,21 @@ module ActiveRecord
53
58
  end
54
59
 
55
60
  def structure_load(filename, extra_flags)
56
- dbfile = configuration["database"]
57
61
  flags = extra_flags.join(" ") if extra_flags
58
- `sqlite3 #{flags} #{dbfile} < "#{filename}"`
62
+ `sqlite3 #{flags} #{db_config.database} < "#{filename}"`
59
63
  end
60
64
 
61
65
  private
66
+ attr_reader :db_config, :root
62
67
 
63
- attr_reader :configuration, :root
68
+ def connection
69
+ ActiveRecord::Base.lease_connection
70
+ end
71
+
72
+ def establish_connection(config = db_config)
73
+ ActiveRecord::Base.establish_connection(config)
74
+ connection.connect!
75
+ end
64
76
 
65
77
  def run_cmd(cmd, args, out)
66
78
  fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
@@ -5,18 +5,19 @@ require "active_support/testing/parallelization"
5
5
  module ActiveRecord
6
6
  module TestDatabases # :nodoc:
7
7
  ActiveSupport::Testing::Parallelization.after_fork_hook do |i|
8
- create_and_load_schema(i, env_name: Rails.env)
8
+ create_and_load_schema(i, env_name: ActiveRecord::ConnectionHandling::DEFAULT_ENV.call)
9
9
  end
10
10
 
11
11
  def self.create_and_load_schema(i, env_name:)
12
12
  old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
13
13
 
14
14
  ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
15
- db_config.config["database"] += "-#{i}"
16
- ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config.config, ActiveRecord::Base.schema_format, nil, env_name, db_config.spec_name)
15
+ db_config._database = "#{db_config.database}-#{i}"
16
+
17
+ ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord.schema_format, nil)
17
18
  end
18
19
  ensure
19
- ActiveRecord::Base.establish_connection(Rails.env.to_sym)
20
+ ActiveRecord::Base.establish_connection
20
21
  ENV["VERBOSE"] = old
21
22
  end
22
23
  end