activerecord 4.2.0 → 6.1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1221 -796
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +267 -249
  8. data/lib/active_record/association_relation.rb +45 -7
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +172 -67
  11. data/lib/active_record/associations/association_scope.rb +105 -129
  12. data/lib/active_record/associations/belongs_to_association.rb +85 -59
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -33
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +168 -279
  22. data/lib/active_record/associations/collection_proxy.rb +263 -155
  23. data/lib/active_record/associations/foreign_association.rb +33 -0
  24. data/lib/active_record/associations/has_many_association.rb +57 -84
  25. data/lib/active_record/associations/has_many_through_association.rb +70 -82
  26. data/lib/active_record/associations/has_one_association.rb +74 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +175 -164
  32. data/lib/active_record/associations/preloader/association.rb +107 -112
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +99 -96
  35. data/lib/active_record/associations/singular_association.rb +18 -45
  36. data/lib/active_record/associations/through_association.rb +49 -24
  37. data/lib/active_record/associations.rb +1845 -1597
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -138
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
  46. data/lib/active_record/attribute_methods/write.rb +25 -56
  47. data/lib/active_record/attribute_methods.rb +153 -162
  48. data/lib/active_record/attributes.rb +234 -70
  49. data/lib/active_record/autosave_association.rb +157 -69
  50. data/lib/active_record/base.rb +49 -50
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +46 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
  119. data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +488 -243
  133. data/lib/active_record/counter_cache.rb +71 -50
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +273 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +212 -94
  143. data/lib/active_record/errors.rb +225 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +11 -6
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +273 -496
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +64 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +52 -0
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +103 -95
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +298 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +685 -309
  170. data/lib/active_record/model_schema.rb +420 -113
  171. data/lib/active_record/nested_attributes.rb +265 -216
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +574 -135
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +175 -54
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +533 -216
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +485 -310
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +326 -244
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +318 -256
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +99 -84
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +139 -96
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -409
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +23 -21
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -342
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -26
  209. data/lib/active_record/scoping/default.rb +96 -82
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +133 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +366 -129
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +291 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +181 -152
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -41
  231. data/lib/active_record/type/date_time.rb +4 -38
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +33 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +65 -48
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +44 -28
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +175 -65
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  347. data/lib/active_record/attribute.rb +0 -149
  348. data/lib/active_record/attribute_decorators.rb +0 -66
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  352. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  353. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  354. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  355. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  356. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  357. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  358. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  359. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  360. data/lib/active_record/type/big_integer.rb +0 -13
  361. data/lib/active_record/type/binary.rb +0 -50
  362. data/lib/active_record/type/boolean.rb +0 -30
  363. data/lib/active_record/type/decimal.rb +0 -40
  364. data/lib/active_record/type/decorator.rb +0 -14
  365. data/lib/active_record/type/float.rb +0 -19
  366. data/lib/active_record/type/integer.rb +0 -55
  367. data/lib/active_record/type/mutable.rb +0 -16
  368. data/lib/active_record/type/numeric.rb +0 -36
  369. data/lib/active_record/type/string.rb +0 -36
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -101
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  374. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,50 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Tasks # :nodoc:
3
5
  class MySQLDatabaseTasks # :nodoc:
4
- DEFAULT_CHARSET = ENV['CHARSET'] || 'utf8'
5
- DEFAULT_COLLATION = ENV['COLLATION'] || 'utf8_unicode_ci'
6
- ACCESS_DENIED_ERROR = 1045
6
+ ER_DB_CREATE_EXISTS = 1007
7
7
 
8
8
  delegate :connection, :establish_connection, to: ActiveRecord::Base
9
9
 
10
- def initialize(configuration)
11
- @configuration = configuration
10
+ def self.using_database_configurations?
11
+ true
12
+ end
13
+
14
+ def initialize(db_config)
15
+ @db_config = db_config
16
+ @configuration_hash = db_config.configuration_hash
12
17
  end
13
18
 
14
19
  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 /database exists/ === error.message
20
- raise DatabaseAlreadyExists
21
- else
22
- raise
23
- end
24
- rescue error_class => error
25
- if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR
26
- $stdout.print error.error
27
- establish_connection root_configuration_without_database
28
- connection.create_database configuration['database'], creation_options
29
- if configuration['username'] != 'root'
30
- connection.execute grant_statement.gsub(/\s+/, ' ').strip
31
- end
32
- establish_connection configuration
33
- else
34
- $stderr.puts error.inspect
35
- $stderr.puts "Couldn't create database for #{configuration.inspect}, #{creation_options.inspect}"
36
- $stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration['encoding']
37
- end
20
+ establish_connection(configuration_hash_without_database)
21
+ connection.create_database(db_config.database, creation_options)
22
+ establish_connection(db_config)
38
23
  end
39
24
 
40
25
  def drop
41
- establish_connection configuration
42
- connection.drop_database configuration['database']
26
+ establish_connection(db_config)
27
+ connection.drop_database(db_config.database)
43
28
  end
44
29
 
45
30
  def purge
46
- establish_connection configuration
47
- connection.recreate_database configuration['database'], creation_options
31
+ establish_connection(db_config)
32
+ connection.recreate_database(db_config.database, creation_options)
48
33
  end
49
34
 
50
35
  def charset
@@ -55,91 +40,74 @@ module ActiveRecord
55
40
  connection.collation
56
41
  end
57
42
 
58
- def structure_dump(filename)
59
- args = prepare_command_options('mysqldump')
43
+ def structure_dump(filename, extra_flags)
44
+ args = prepare_command_options
60
45
  args.concat(["--result-file", "#{filename}"])
61
46
  args.concat(["--no-data"])
62
- args.concat(["#{configuration['database']}"])
63
- unless Kernel.system(*args)
64
- $stderr.puts "Could not dump the database structure. "\
65
- "Make sure `mysqldump` is in your PATH and check the command output for warnings."
66
- end
67
- end
47
+ args.concat(["--routines"])
48
+ args.concat(["--skip-comments"])
68
49
 
69
- def structure_load(filename)
70
- args = prepare_command_options('mysql')
71
- args.concat(['--execute', %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
72
- args.concat(["--database", "#{configuration['database']}"])
73
- Kernel.system(*args)
74
- end
50
+ ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
51
+ if ignore_tables.any?
52
+ args += ignore_tables.map { |table| "--ignore-table=#{db_config.database}.#{table}" }
53
+ end
75
54
 
76
- private
55
+ args.concat([db_config.database.to_s])
56
+ args.unshift(*extra_flags) if extra_flags
77
57
 
78
- def configuration
79
- @configuration
58
+ run_cmd("mysqldump", args, "dumping")
80
59
  end
81
60
 
82
- def configuration_without_database
83
- configuration.merge('database' => nil)
84
- end
61
+ def structure_load(filename, extra_flags)
62
+ args = prepare_command_options
63
+ args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
64
+ args.concat(["--database", db_config.database.to_s])
65
+ args.unshift(*extra_flags) if extra_flags
85
66
 
86
- def creation_options
87
- Hash.new.tap do |options|
88
- options[:charset] = configuration['encoding'] if configuration.include? 'encoding'
89
- options[:collation] = configuration['collation'] if configuration.include? 'collation'
67
+ run_cmd("mysql", args, "loading")
68
+ end
90
69
 
91
- # Set default charset only when collation isn't set.
92
- options[:charset] ||= DEFAULT_CHARSET unless options[:collation]
70
+ private
71
+ attr_reader :db_config, :configuration_hash
93
72
 
94
- # Set default collation only when charset is also default.
95
- options[:collation] ||= DEFAULT_COLLATION if options[:charset] == DEFAULT_CHARSET
73
+ def configuration_hash_without_database
74
+ configuration_hash.merge(database: nil)
96
75
  end
97
- end
98
76
 
99
- def error_class
100
- if configuration['adapter'] =~ /jdbc/
101
- require 'active_record/railties/jdbcmysql_error'
102
- ArJdbcMySQL::Error
103
- elsif defined?(Mysql2)
104
- Mysql2::Error
105
- elsif defined?(Mysql)
106
- Mysql::Error
107
- else
108
- StandardError
77
+ def creation_options
78
+ Hash.new.tap do |options|
79
+ options[:charset] = configuration_hash[:encoding] if configuration_hash.include?(:encoding)
80
+ options[:collation] = configuration_hash[:collation] if configuration_hash.include?(:collation)
81
+ end
109
82
  end
110
- end
111
-
112
- def grant_statement
113
- <<-SQL
114
- GRANT ALL PRIVILEGES ON #{configuration['database']}.*
115
- TO '#{configuration['username']}'@'localhost'
116
- IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
117
- SQL
118
- end
119
83
 
120
- def root_configuration_without_database
121
- configuration_without_database.merge(
122
- 'username' => 'root',
123
- 'password' => root_password
124
- )
125
- end
126
-
127
- def root_password
128
- $stdout.print "Please provide the root password for your MySQL installation\n>"
129
- $stdin.gets.strip
130
- end
84
+ def prepare_command_options
85
+ args = {
86
+ host: "--host",
87
+ port: "--port",
88
+ socket: "--socket",
89
+ username: "--user",
90
+ password: "--password",
91
+ encoding: "--default-character-set",
92
+ sslca: "--ssl-ca",
93
+ sslcert: "--ssl-cert",
94
+ sslcapath: "--ssl-capath",
95
+ sslcipher: "--ssl-cipher",
96
+ sslkey: "--ssl-key"
97
+ }.map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }.compact
98
+
99
+ args
100
+ end
131
101
 
132
- def prepare_command_options(command)
133
- args = [command]
134
- args.concat(['--user', configuration['username']]) if configuration['username']
135
- args << "--password=#{configuration['password']}" if configuration['password']
136
- args.concat(['--default-character-set', configuration['encoding']]) if configuration['encoding']
137
- configuration.slice('host', 'port', 'socket').each do |k, v|
138
- args.concat([ "--#{k}", v.to_s ]) if v
102
+ def run_cmd(cmd, args, action)
103
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
139
104
  end
140
105
 
141
- args
142
- end
106
+ def run_cmd_error(cmd, args, action)
107
+ msg = +"failed to execute: `#{cmd}`\n"
108
+ msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
109
+ msg
110
+ end
143
111
  end
144
112
  end
145
113
  end
@@ -1,33 +1,35 @@
1
- require 'shellwords'
1
+ # frozen_string_literal: true
2
+
3
+ require "tempfile"
2
4
 
3
5
  module ActiveRecord
4
6
  module Tasks # :nodoc:
5
7
  class PostgreSQLDatabaseTasks # :nodoc:
6
- DEFAULT_ENCODING = ENV['CHARSET'] || 'utf8'
8
+ DEFAULT_ENCODING = ENV["CHARSET"] || "utf8"
9
+ ON_ERROR_STOP_1 = "ON_ERROR_STOP=1"
10
+ SQL_COMMENT_BEGIN = "--"
7
11
 
8
12
  delegate :connection, :establish_connection, :clear_active_connections!,
9
13
  to: ActiveRecord::Base
10
14
 
11
- def initialize(configuration)
12
- @configuration = configuration
15
+ def self.using_database_configurations?
16
+ true
17
+ end
18
+
19
+ def initialize(db_config)
20
+ @db_config = db_config
21
+ @configuration_hash = db_config.configuration_hash
13
22
  end
14
23
 
15
24
  def create(master_established = false)
16
25
  establish_master_connection unless master_established
17
- connection.create_database configuration['database'],
18
- configuration.merge('encoding' => encoding)
19
- establish_connection configuration
20
- rescue ActiveRecord::StatementInvalid => error
21
- if /database .* already exists/ === error.message
22
- raise DatabaseAlreadyExists
23
- else
24
- raise
25
- end
26
+ connection.create_database(db_config.database, configuration_hash.merge(encoding: encoding))
27
+ establish_connection(db_config)
26
28
  end
27
29
 
28
30
  def drop
29
31
  establish_master_connection
30
- connection.drop_database configuration['database']
32
+ connection.drop_database(db_config.database)
31
33
  end
32
34
 
33
35
  def charset
@@ -44,47 +46,93 @@ module ActiveRecord
44
46
  create true
45
47
  end
46
48
 
47
- def structure_dump(filename)
49
+ def structure_dump(filename, extra_flags)
48
50
  set_psql_env
49
- search_path = configuration['schema_search_path']
51
+
52
+ search_path = \
53
+ case ActiveRecord::Base.dump_schemas
54
+ when :schema_search_path
55
+ configuration_hash[:schema_search_path]
56
+ when :all
57
+ nil
58
+ when String
59
+ ActiveRecord::Base.dump_schemas
60
+ end
61
+
62
+ args = ["--schema-only", "--no-privileges", "--no-owner", "--file", filename]
63
+ args.concat(Array(extra_flags)) if extra_flags
50
64
  unless search_path.blank?
51
- search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ")
65
+ args += search_path.split(",").map do |part|
66
+ "--schema=#{part.strip}"
67
+ end
52
68
  end
53
69
 
54
- command = "pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(configuration['database'])}"
55
- raise 'Error dumping database' unless Kernel.system(command)
70
+ ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
71
+ if ignore_tables.any?
72
+ args += ignore_tables.flat_map { |table| ["-T", table] }
73
+ end
56
74
 
75
+ args << db_config.database
76
+ run_cmd("pg_dump", args, "dumping")
77
+ remove_sql_header_comments(filename)
57
78
  File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
58
79
  end
59
80
 
60
- def structure_load(filename)
81
+ def structure_load(filename, extra_flags)
61
82
  set_psql_env
62
- Kernel.system("psql -q -f #{Shellwords.escape(filename)} #{configuration['database']}")
83
+ args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--file", filename]
84
+ args.concat(Array(extra_flags)) if extra_flags
85
+ args << db_config.database
86
+ run_cmd("psql", args, "loading")
63
87
  end
64
88
 
65
89
  private
90
+ attr_reader :db_config, :configuration_hash
66
91
 
67
- def configuration
68
- @configuration
69
- end
92
+ def encoding
93
+ configuration_hash[:encoding] || DEFAULT_ENCODING
94
+ end
70
95
 
71
- def encoding
72
- configuration['encoding'] || DEFAULT_ENCODING
73
- end
96
+ def establish_master_connection
97
+ establish_connection configuration_hash.merge(
98
+ database: "postgres",
99
+ schema_search_path: "public"
100
+ )
101
+ end
74
102
 
75
- def establish_master_connection
76
- establish_connection configuration.merge(
77
- 'database' => 'postgres',
78
- 'schema_search_path' => 'public'
79
- )
80
- end
103
+ def set_psql_env
104
+ ENV["PGHOST"] = db_config.host if db_config.host
105
+ ENV["PGPORT"] = configuration_hash[:port].to_s if configuration_hash[:port]
106
+ ENV["PGPASSWORD"] = configuration_hash[:password].to_s if configuration_hash[:password]
107
+ ENV["PGUSER"] = configuration_hash[:username].to_s if configuration_hash[:username]
108
+ end
81
109
 
82
- def set_psql_env
83
- ENV['PGHOST'] = configuration['host'] if configuration['host']
84
- ENV['PGPORT'] = configuration['port'].to_s if configuration['port']
85
- ENV['PGPASSWORD'] = configuration['password'].to_s if configuration['password']
86
- ENV['PGUSER'] = configuration['username'].to_s if configuration['username']
87
- end
110
+ def run_cmd(cmd, args, action)
111
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
112
+ end
113
+
114
+ def run_cmd_error(cmd, args, action)
115
+ msg = +"failed to execute:\n"
116
+ msg << "#{cmd} #{args.join(' ')}\n\n"
117
+ msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
118
+ msg
119
+ end
120
+
121
+ def remove_sql_header_comments(filename)
122
+ removing_comments = true
123
+ tempfile = Tempfile.open("uncommented_structure.sql")
124
+ begin
125
+ File.foreach(filename) do |line|
126
+ unless removing_comments && (line.start_with?(SQL_COMMENT_BEGIN) || line.blank?)
127
+ tempfile << line
128
+ removing_comments = false
129
+ end
130
+ end
131
+ ensure
132
+ tempfile.close
133
+ end
134
+ FileUtils.cp(tempfile.path, filename)
135
+ end
88
136
  end
89
137
  end
90
138
  end
@@ -1,29 +1,40 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Tasks # :nodoc:
3
5
  class SQLiteDatabaseTasks # :nodoc:
4
6
  delegate :connection, :establish_connection, to: ActiveRecord::Base
5
7
 
6
- def initialize(configuration, root = ActiveRecord::Tasks::DatabaseTasks.root)
7
- @configuration, @root = configuration, root
8
+ def self.using_database_configurations?
9
+ true
10
+ end
11
+
12
+ def initialize(db_config, root = ActiveRecord::Tasks::DatabaseTasks.root)
13
+ @db_config = db_config
14
+ @root = root
8
15
  end
9
16
 
10
17
  def create
11
- raise DatabaseAlreadyExists if File.exist?(configuration['database'])
18
+ raise DatabaseAlreadyExists if File.exist?(db_config.database)
12
19
 
13
- establish_connection configuration
20
+ establish_connection(db_config)
14
21
  connection
15
22
  end
16
23
 
17
24
  def drop
18
- require 'pathname'
19
- path = Pathname.new configuration['database']
25
+ require "pathname"
26
+ path = Pathname.new(db_config.database)
20
27
  file = path.absolute? ? path.to_s : File.join(root, path)
21
28
 
22
- FileUtils.rm(file) if File.exist?(file)
29
+ FileUtils.rm(file)
30
+ rescue Errno::ENOENT => error
31
+ raise NoDatabaseError.new(error.message)
23
32
  end
24
33
 
25
34
  def purge
26
35
  drop
36
+ rescue NoDatabaseError
37
+ ensure
27
38
  create
28
39
  end
29
40
 
@@ -31,25 +42,39 @@ module ActiveRecord
31
42
  connection.encoding
32
43
  end
33
44
 
34
- def structure_dump(filename)
35
- dbfile = configuration['database']
36
- `sqlite3 #{dbfile} .schema > #{filename}`
45
+ def structure_dump(filename, extra_flags)
46
+ args = []
47
+ args.concat(Array(extra_flags)) if extra_flags
48
+ args << db_config.database
49
+
50
+ ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
51
+ if ignore_tables.any?
52
+ condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
53
+ args << "SELECT sql FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
54
+ else
55
+ args << ".schema"
56
+ end
57
+ run_cmd("sqlite3", args, filename)
37
58
  end
38
59
 
39
- def structure_load(filename)
40
- dbfile = configuration['database']
41
- `sqlite3 #{dbfile} < "#{filename}"`
60
+ def structure_load(filename, extra_flags)
61
+ flags = extra_flags.join(" ") if extra_flags
62
+ `sqlite3 #{flags} #{db_config.database} < "#{filename}"`
42
63
  end
43
64
 
44
65
  private
66
+ attr_reader :db_config, :root
45
67
 
46
- def configuration
47
- @configuration
48
- end
68
+ def run_cmd(cmd, args, out)
69
+ fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
70
+ end
49
71
 
50
- def root
51
- @root
52
- end
72
+ def run_cmd_error(cmd, args)
73
+ msg = +"failed to execute:\n"
74
+ msg << "#{cmd} #{args.join(' ')}\n\n"
75
+ msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
76
+ msg
77
+ end
53
78
  end
54
79
  end
55
80
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/testing/parallelization"
4
+
5
+ module ActiveRecord
6
+ module TestDatabases # :nodoc:
7
+ ActiveSupport::Testing::Parallelization.after_fork_hook do |i|
8
+ create_and_load_schema(i, env_name: ActiveRecord::ConnectionHandling::DEFAULT_ENV.call)
9
+ end
10
+
11
+ def self.create_and_load_schema(i, env_name:)
12
+ old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
13
+
14
+ ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
15
+ db_config._database = "#{db_config.database}-#{i}"
16
+
17
+ ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord::Base.schema_format, nil)
18
+ end
19
+ ensure
20
+ ActiveRecord::Base.establish_connection
21
+ ENV["VERBOSE"] = old
22
+ end
23
+ end
24
+ end