activerecord 6.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (340) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1086 -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.rb +195 -0
  8. data/lib/active_record/aggregations.rb +285 -0
  9. data/lib/active_record/association_relation.rb +49 -0
  10. data/lib/active_record/associations.rb +1865 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +340 -0
  13. data/lib/active_record/associations/association_scope.rb +166 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +124 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +36 -0
  16. data/lib/active_record/associations/builder/association.rb +136 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +130 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +72 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +114 -0
  20. data/lib/active_record/associations/builder/has_many.rb +19 -0
  21. data/lib/active_record/associations/builder/has_one.rb +64 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +44 -0
  23. data/lib/active_record/associations/collection_association.rb +498 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1128 -0
  25. data/lib/active_record/associations/foreign_association.rb +20 -0
  26. data/lib/active_record/associations/has_many_association.rb +136 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +220 -0
  28. data/lib/active_record/associations/has_one_association.rb +118 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +262 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +80 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +201 -0
  35. data/lib/active_record/associations/preloader/association.rb +133 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +116 -0
  37. data/lib/active_record/associations/singular_association.rb +59 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +85 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +420 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +81 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +221 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +136 -0
  45. data/lib/active_record/attribute_methods/query.rb +41 -0
  46. data/lib/active_record/attribute_methods/read.rb +47 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +61 -0
  50. data/lib/active_record/attributes.rb +279 -0
  51. data/lib/active_record/autosave_association.rb +512 -0
  52. data/lib/active_record/base.rb +328 -0
  53. data/lib/active_record/callbacks.rb +339 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1175 -0
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +85 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +516 -0
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +155 -0
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +251 -0
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +713 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1475 -0
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +772 -0
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +830 -0
  69. data/lib/active_record/connection_adapters/column.rb +95 -0
  70. data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +202 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +146 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +184 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +953 -0
  117. data/lib/active_record/connection_adapters/schema_cache.rb +141 -0
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +561 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +274 -0
  129. data/lib/active_record/core.rb +603 -0
  130. data/lib/active_record/counter_cache.rb +193 -0
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +122 -0
  137. data/lib/active_record/enum.rb +274 -0
  138. data/lib/active_record/errors.rb +388 -0
  139. data/lib/active_record/explain.rb +50 -0
  140. data/lib/active_record/explain_registry.rb +32 -0
  141. data/lib/active_record/explain_subscriber.rb +34 -0
  142. data/lib/active_record/fixture_set/file.rb +82 -0
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +738 -0
  148. data/lib/active_record/gem_version.rb +17 -0
  149. data/lib/active_record/inheritance.rb +293 -0
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +207 -0
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  154. data/lib/active_record/locale/en.yml +48 -0
  155. data/lib/active_record/locking/optimistic.rb +197 -0
  156. data/lib/active_record/locking/pessimistic.rb +89 -0
  157. data/lib/active_record/log_subscriber.rb +118 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +1397 -0
  162. data/lib/active_record/migration/command_recorder.rb +284 -0
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +17 -0
  165. data/lib/active_record/model_schema.rb +545 -0
  166. data/lib/active_record/nested_attributes.rb +600 -0
  167. data/lib/active_record/no_touching.rb +65 -0
  168. data/lib/active_record/null_relation.rb +68 -0
  169. data/lib/active_record/persistence.rb +967 -0
  170. data/lib/active_record/query_cache.rb +52 -0
  171. data/lib/active_record/querying.rb +82 -0
  172. data/lib/active_record/railtie.rb +263 -0
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +7 -0
  175. data/lib/active_record/railties/controller_runtime.rb +51 -0
  176. data/lib/active_record/railties/databases.rake +527 -0
  177. data/lib/active_record/readonly_attributes.rb +24 -0
  178. data/lib/active_record/reflection.rb +1042 -0
  179. data/lib/active_record/relation.rb +860 -0
  180. data/lib/active_record/relation/batches.rb +290 -0
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +424 -0
  183. data/lib/active_record/relation/delegation.rb +130 -0
  184. data/lib/active_record/relation/finder_methods.rb +561 -0
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +184 -0
  187. data/lib/active_record/relation/predicate_builder.rb +150 -0
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +1371 -0
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +77 -0
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +168 -0
  202. data/lib/active_record/runtime_registry.rb +24 -0
  203. data/lib/active_record/sanitization.rb +214 -0
  204. data/lib/active_record/schema.rb +61 -0
  205. data/lib/active_record/schema_dumper.rb +270 -0
  206. data/lib/active_record/schema_migration.rb +60 -0
  207. data/lib/active_record/scoping.rb +106 -0
  208. data/lib/active_record/scoping/default.rb +151 -0
  209. data/lib/active_record/scoping/named.rb +217 -0
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +22 -0
  212. data/lib/active_record/statement_cache.rb +148 -0
  213. data/lib/active_record/store.rb +290 -0
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +506 -0
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +224 -0
  222. data/lib/active_record/timestamp.rb +167 -0
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +493 -0
  225. data/lib/active_record/translation.rb +24 -0
  226. data/lib/active_record/type.rb +78 -0
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +9 -0
  229. data/lib/active_record/type/date_time.rb +9 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +71 -0
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +21 -0
  237. data/lib/active_record/type/type_map.rb +62 -0
  238. data/lib/active_record/type/unsigned_integer.rb +17 -0
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +94 -0
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +60 -0
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +68 -0
  247. data/lib/active_record/validations/uniqueness.rb +226 -0
  248. data/lib/active_record/version.rb +10 -0
  249. data/lib/arel.rb +58 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +19 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration.rb +48 -0
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +75 -0
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  337. data/lib/rails/generators/active_record/model/model_generator.rb +49 -0
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  340. metadata +418 -0
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Tasks # :nodoc:
5
+ class MySQLDatabaseTasks # :nodoc:
6
+ ER_DB_CREATE_EXISTS = 1007
7
+
8
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
9
+
10
+ def initialize(configuration)
11
+ @configuration = configuration
12
+ end
13
+
14
+ 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
24
+ end
25
+
26
+ def drop
27
+ establish_connection configuration
28
+ connection.drop_database configuration["database"]
29
+ end
30
+
31
+ def purge
32
+ establish_connection configuration
33
+ connection.recreate_database configuration["database"], creation_options
34
+ end
35
+
36
+ def charset
37
+ connection.charset
38
+ end
39
+
40
+ def collation
41
+ connection.collation
42
+ end
43
+
44
+ def structure_dump(filename, extra_flags)
45
+ args = prepare_command_options
46
+ args.concat(["--result-file", "#{filename}"])
47
+ args.concat(["--no-data"])
48
+ args.concat(["--routines"])
49
+ args.concat(["--skip-comments"])
50
+
51
+ ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
52
+ if ignore_tables.any?
53
+ args += ignore_tables.map { |table| "--ignore-table=#{configuration['database']}.#{table}" }
54
+ end
55
+
56
+ args.concat(["#{configuration['database']}"])
57
+ args.unshift(*extra_flags) if extra_flags
58
+
59
+ run_cmd("mysqldump", args, "dumping")
60
+ end
61
+
62
+ def structure_load(filename, extra_flags)
63
+ args = prepare_command_options
64
+ args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
65
+ args.concat(["--database", "#{configuration['database']}"])
66
+ args.unshift(*extra_flags) if extra_flags
67
+
68
+ run_cmd("mysql", args, "loading")
69
+ end
70
+
71
+ private
72
+
73
+ attr_reader :configuration
74
+
75
+ def configuration_without_database
76
+ configuration.merge("database" => nil)
77
+ end
78
+
79
+ def creation_options
80
+ Hash.new.tap do |options|
81
+ options[:charset] = configuration["encoding"] if configuration.include? "encoding"
82
+ options[:collation] = configuration["collation"] if configuration.include? "collation"
83
+ end
84
+ end
85
+
86
+ def prepare_command_options
87
+ 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
100
+
101
+ args
102
+ end
103
+
104
+ def run_cmd(cmd, args, action)
105
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
106
+ end
107
+
108
+ def run_cmd_error(cmd, args, action)
109
+ msg = +"failed to execute: `#{cmd}`\n"
110
+ 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"
111
+ msg
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tempfile"
4
+
5
+ module ActiveRecord
6
+ module Tasks # :nodoc:
7
+ class PostgreSQLDatabaseTasks # :nodoc:
8
+ DEFAULT_ENCODING = ENV["CHARSET"] || "utf8"
9
+ ON_ERROR_STOP_1 = "ON_ERROR_STOP=1"
10
+ SQL_COMMENT_BEGIN = "--"
11
+
12
+ delegate :connection, :establish_connection, :clear_active_connections!,
13
+ to: ActiveRecord::Base
14
+
15
+ def initialize(configuration)
16
+ @configuration = configuration
17
+ end
18
+
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
30
+ end
31
+
32
+ def drop
33
+ establish_master_connection
34
+ connection.drop_database configuration["database"]
35
+ end
36
+
37
+ def charset
38
+ connection.encoding
39
+ end
40
+
41
+ def collation
42
+ connection.collation
43
+ end
44
+
45
+ def purge
46
+ clear_active_connections!
47
+ drop
48
+ create true
49
+ end
50
+
51
+ def structure_dump(filename, extra_flags)
52
+ set_psql_env
53
+
54
+ search_path = \
55
+ case ActiveRecord::Base.dump_schemas
56
+ when :schema_search_path
57
+ configuration["schema_search_path"]
58
+ when :all
59
+ nil
60
+ when String
61
+ ActiveRecord::Base.dump_schemas
62
+ end
63
+
64
+ args = ["-s", "-x", "-O", "-f", filename]
65
+ args.concat(Array(extra_flags)) if extra_flags
66
+ unless search_path.blank?
67
+ args += search_path.split(",").map do |part|
68
+ "--schema=#{part.strip}"
69
+ end
70
+ end
71
+
72
+ ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
73
+ if ignore_tables.any?
74
+ args += ignore_tables.flat_map { |table| ["-T", table] }
75
+ end
76
+
77
+ args << configuration["database"]
78
+ run_cmd("pg_dump", args, "dumping")
79
+ remove_sql_header_comments(filename)
80
+ File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
81
+ end
82
+
83
+ def structure_load(filename, extra_flags)
84
+ set_psql_env
85
+ args = ["-v", ON_ERROR_STOP_1, "-q", "-X", "-f", filename]
86
+ args.concat(Array(extra_flags)) if extra_flags
87
+ args << configuration["database"]
88
+ run_cmd("psql", args, "loading")
89
+ end
90
+
91
+ private
92
+
93
+ attr_reader :configuration
94
+
95
+ def encoding
96
+ configuration["encoding"] || DEFAULT_ENCODING
97
+ end
98
+
99
+ def establish_master_connection
100
+ establish_connection configuration.merge(
101
+ "database" => "postgres",
102
+ "schema_search_path" => "public"
103
+ )
104
+ end
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"]
111
+ end
112
+
113
+ def run_cmd(cmd, args, action)
114
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
115
+ end
116
+
117
+ def run_cmd_error(cmd, args, action)
118
+ msg = +"failed to execute:\n"
119
+ msg << "#{cmd} #{args.join(' ')}\n\n"
120
+ 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"
121
+ msg
122
+ end
123
+
124
+ def remove_sql_header_comments(filename)
125
+ removing_comments = true
126
+ tempfile = Tempfile.open("uncommented_structure.sql")
127
+ begin
128
+ File.foreach(filename) do |line|
129
+ unless removing_comments && (line.start_with?(SQL_COMMENT_BEGIN) || line.blank?)
130
+ tempfile << line
131
+ removing_comments = false
132
+ end
133
+ end
134
+ ensure
135
+ tempfile.close
136
+ end
137
+ FileUtils.cp(tempfile.path, filename)
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Tasks # :nodoc:
5
+ class SQLiteDatabaseTasks # :nodoc:
6
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
7
+
8
+ def initialize(configuration, root = ActiveRecord::Tasks::DatabaseTasks.root)
9
+ @configuration, @root = configuration, root
10
+ end
11
+
12
+ def create
13
+ raise DatabaseAlreadyExists if File.exist?(configuration["database"])
14
+
15
+ establish_connection configuration
16
+ connection
17
+ end
18
+
19
+ def drop
20
+ require "pathname"
21
+ path = Pathname.new configuration["database"]
22
+ file = path.absolute? ? path.to_s : File.join(root, path)
23
+
24
+ FileUtils.rm(file)
25
+ rescue Errno::ENOENT => error
26
+ raise NoDatabaseError.new(error.message)
27
+ end
28
+
29
+ def purge
30
+ drop
31
+ rescue NoDatabaseError
32
+ ensure
33
+ create
34
+ end
35
+
36
+ def charset
37
+ connection.encoding
38
+ end
39
+
40
+ def structure_dump(filename, extra_flags)
41
+ args = []
42
+ args.concat(Array(extra_flags)) if extra_flags
43
+ args << configuration["database"]
44
+
45
+ ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
46
+ if ignore_tables.any?
47
+ condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
48
+ args << "SELECT sql FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
49
+ else
50
+ args << ".schema"
51
+ end
52
+ run_cmd("sqlite3", args, filename)
53
+ end
54
+
55
+ def structure_load(filename, extra_flags)
56
+ dbfile = configuration["database"]
57
+ flags = extra_flags.join(" ") if extra_flags
58
+ `sqlite3 #{flags} #{dbfile} < "#{filename}"`
59
+ end
60
+
61
+ private
62
+
63
+ attr_reader :configuration, :root
64
+
65
+ def run_cmd(cmd, args, out)
66
+ fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
67
+ end
68
+
69
+ def run_cmd_error(cmd, args)
70
+ msg = +"failed to execute:\n"
71
+ msg << "#{cmd} #{args.join(' ')}\n\n"
72
+ 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"
73
+ msg
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,23 @@
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: Rails.env)
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.config["database"] += "-#{i}"
16
+ ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config.config, ActiveRecord::Base.schema_format, nil, env_name, db_config.spec_name)
17
+ end
18
+ ensure
19
+ ActiveRecord::Base.establish_connection(Rails.env.to_sym)
20
+ ENV["VERBOSE"] = old
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,224 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module TestFixtures
5
+ extend ActiveSupport::Concern
6
+
7
+ def before_setup # :nodoc:
8
+ setup_fixtures
9
+ super
10
+ end
11
+
12
+ def after_teardown # :nodoc:
13
+ super
14
+ teardown_fixtures
15
+ end
16
+
17
+ included do
18
+ class_attribute :fixture_path, instance_writer: false
19
+ class_attribute :fixture_table_names, default: []
20
+ class_attribute :fixture_class_names, default: {}
21
+ class_attribute :use_transactional_tests, default: true
22
+ class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
23
+ class_attribute :pre_loaded_fixtures, default: false
24
+ class_attribute :config, default: ActiveRecord::Base
25
+ class_attribute :lock_threads, default: true
26
+ end
27
+
28
+ module ClassMethods
29
+ # Sets the model class for a fixture when the class name cannot be inferred from the fixture name.
30
+ #
31
+ # Examples:
32
+ #
33
+ # set_fixture_class some_fixture: SomeModel,
34
+ # 'namespaced/fixture' => Another::Model
35
+ #
36
+ # The keys must be the fixture names, that coincide with the short paths to the fixture files.
37
+ def set_fixture_class(class_names = {})
38
+ self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
39
+ end
40
+
41
+ def fixtures(*fixture_set_names)
42
+ if fixture_set_names.first == :all
43
+ raise StandardError, "No fixture path found. Please set `#{self}.fixture_path`." if fixture_path.blank?
44
+ fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"].uniq
45
+ fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
46
+ else
47
+ fixture_set_names = fixture_set_names.flatten.map(&:to_s)
48
+ end
49
+
50
+ self.fixture_table_names |= fixture_set_names
51
+ setup_fixture_accessors(fixture_set_names)
52
+ end
53
+
54
+ def setup_fixture_accessors(fixture_set_names = nil)
55
+ fixture_set_names = Array(fixture_set_names || fixture_table_names)
56
+ methods = Module.new do
57
+ fixture_set_names.each do |fs_name|
58
+ fs_name = fs_name.to_s
59
+ accessor_name = fs_name.tr("/", "_").to_sym
60
+
61
+ define_method(accessor_name) do |*fixture_names|
62
+ force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
63
+ return_single_record = fixture_names.size == 1
64
+ fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
65
+
66
+ @fixture_cache[fs_name] ||= {}
67
+
68
+ instances = fixture_names.map do |f_name|
69
+ f_name = f_name.to_s if f_name.is_a?(Symbol)
70
+ @fixture_cache[fs_name].delete(f_name) if force_reload
71
+
72
+ if @loaded_fixtures[fs_name][f_name]
73
+ @fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
74
+ else
75
+ raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
76
+ end
77
+ end
78
+
79
+ return_single_record ? instances.first : instances
80
+ end
81
+ private accessor_name
82
+ end
83
+ end
84
+ include methods
85
+ end
86
+
87
+ def uses_transaction(*methods)
88
+ @uses_transaction = [] unless defined?(@uses_transaction)
89
+ @uses_transaction.concat methods.map(&:to_s)
90
+ end
91
+
92
+ def uses_transaction?(method)
93
+ @uses_transaction = [] unless defined?(@uses_transaction)
94
+ @uses_transaction.include?(method.to_s)
95
+ end
96
+ end
97
+
98
+ def run_in_transaction?
99
+ use_transactional_tests &&
100
+ !self.class.uses_transaction?(method_name)
101
+ end
102
+
103
+ def setup_fixtures(config = ActiveRecord::Base)
104
+ if pre_loaded_fixtures && !use_transactional_tests
105
+ raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
106
+ end
107
+
108
+ @fixture_cache = {}
109
+ @fixture_connections = []
110
+ @@already_loaded_fixtures ||= {}
111
+ @connection_subscriber = nil
112
+
113
+ # Load fixtures once and begin transaction.
114
+ if run_in_transaction?
115
+ if @@already_loaded_fixtures[self.class]
116
+ @loaded_fixtures = @@already_loaded_fixtures[self.class]
117
+ else
118
+ @loaded_fixtures = load_fixtures(config)
119
+ @@already_loaded_fixtures[self.class] = @loaded_fixtures
120
+ end
121
+
122
+ # Begin transactions for connections already established
123
+ @fixture_connections = enlist_fixture_connections
124
+ @fixture_connections.each do |connection|
125
+ connection.begin_transaction joinable: false, _lazy: false
126
+ connection.pool.lock_thread = true if lock_threads
127
+ end
128
+
129
+ # When connections are established in the future, begin a transaction too
130
+ @connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
131
+ spec_name = payload[:spec_name] if payload.key?(:spec_name)
132
+
133
+ if spec_name
134
+ begin
135
+ connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name)
136
+ rescue ConnectionNotEstablished
137
+ connection = nil
138
+ end
139
+
140
+ if connection && !@fixture_connections.include?(connection)
141
+ connection.begin_transaction joinable: false, _lazy: false
142
+ connection.pool.lock_thread = true if lock_threads
143
+ @fixture_connections << connection
144
+ end
145
+ end
146
+ end
147
+
148
+ # Load fixtures for every test.
149
+ else
150
+ ActiveRecord::FixtureSet.reset_cache
151
+ @@already_loaded_fixtures[self.class] = nil
152
+ @loaded_fixtures = load_fixtures(config)
153
+ end
154
+
155
+ # Instantiate fixtures for every test if requested.
156
+ instantiate_fixtures if use_instantiated_fixtures
157
+ end
158
+
159
+ def teardown_fixtures
160
+ # Rollback changes if a transaction is active.
161
+ if run_in_transaction?
162
+ ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
163
+ @fixture_connections.each do |connection|
164
+ connection.rollback_transaction if connection.transaction_open?
165
+ connection.pool.lock_thread = false
166
+ end
167
+ @fixture_connections.clear
168
+ else
169
+ ActiveRecord::FixtureSet.reset_cache
170
+ end
171
+
172
+ ActiveRecord::Base.clear_active_connections!
173
+ end
174
+
175
+ def enlist_fixture_connections
176
+ setup_shared_connection_pool
177
+
178
+ ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
179
+ end
180
+
181
+ private
182
+
183
+ # Shares the writing connection pool with connections on
184
+ # other handlers.
185
+ #
186
+ # In an application with a primary and replica the test fixtures
187
+ # need to share a connection pool so that the reading connection
188
+ # can see data in the open transaction on the writing connection.
189
+ def setup_shared_connection_pool
190
+ writing_handler = ActiveRecord::Base.connection_handler
191
+
192
+ ActiveRecord::Base.connection_handlers.values.each do |handler|
193
+ if handler != writing_handler
194
+ handler.connection_pool_list.each do |pool|
195
+ name = pool.spec.name
196
+ writing_connection = writing_handler.retrieve_connection_pool(name)
197
+ handler.send(:owner_to_pool)[name] = writing_connection
198
+ end
199
+ end
200
+ end
201
+ end
202
+
203
+ def load_fixtures(config)
204
+ fixtures = ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config)
205
+ Hash[fixtures.map { |f| [f.name, f] }]
206
+ end
207
+
208
+ def instantiate_fixtures
209
+ if pre_loaded_fixtures
210
+ raise RuntimeError, "Load fixtures before instantiating them." if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
211
+ ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
212
+ else
213
+ raise RuntimeError, "Load fixtures before instantiating them." if @loaded_fixtures.nil?
214
+ @loaded_fixtures.each_value do |fixture_set|
215
+ ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
216
+ end
217
+ end
218
+ end
219
+
220
+ def load_instances?
221
+ use_instantiated_fixtures != :no_instances
222
+ end
223
+ end
224
+ end