activerecord 6.0.0

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 +1013 -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 +40 -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 +332 -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 +258 -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 +508 -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 +1165 -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 +512 -0
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +154 -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 +761 -0
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +821 -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 +200 -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 +182 -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 +949 -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 +118 -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 +557 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +267 -0
  129. data/lib/active_record/core.rb +599 -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 +92 -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 +542 -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 +859 -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 +552 -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 +1359 -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 +51 -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 +415 -0
@@ -0,0 +1,713 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters #:nodoc:
5
+ # Abstract representation of an index definition on a table. Instances of
6
+ # this type are typically created and returned by methods in database
7
+ # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes
8
+ class IndexDefinition # :nodoc:
9
+ attr_reader :table, :name, :unique, :columns, :lengths, :orders, :opclasses, :where, :type, :using, :comment
10
+
11
+ def initialize(
12
+ table, name,
13
+ unique = false,
14
+ columns = [],
15
+ lengths: {},
16
+ orders: {},
17
+ opclasses: {},
18
+ where: nil,
19
+ type: nil,
20
+ using: nil,
21
+ comment: nil
22
+ )
23
+ @table = table
24
+ @name = name
25
+ @unique = unique
26
+ @columns = columns
27
+ @lengths = concise_options(lengths)
28
+ @orders = concise_options(orders)
29
+ @opclasses = concise_options(opclasses)
30
+ @where = where
31
+ @type = type
32
+ @using = using
33
+ @comment = comment
34
+ end
35
+
36
+ private
37
+ def concise_options(options)
38
+ if columns.size == options.size && options.values.uniq.size == 1
39
+ options.values.first
40
+ else
41
+ options
42
+ end
43
+ end
44
+ end
45
+
46
+ # Abstract representation of a column definition. Instances of this type
47
+ # are typically created by methods in TableDefinition, and added to the
48
+ # +columns+ attribute of said TableDefinition object, in order to be used
49
+ # for generating a number of table creation or table changing SQL statements.
50
+ ColumnDefinition = Struct.new(:name, :type, :options, :sql_type) do # :nodoc:
51
+ def primary_key?
52
+ options[:primary_key]
53
+ end
54
+
55
+ [:limit, :precision, :scale, :default, :null, :collation, :comment].each do |option_name|
56
+ module_eval <<-CODE, __FILE__, __LINE__ + 1
57
+ def #{option_name}
58
+ options[:#{option_name}]
59
+ end
60
+
61
+ def #{option_name}=(value)
62
+ options[:#{option_name}] = value
63
+ end
64
+ CODE
65
+ end
66
+ end
67
+
68
+ AddColumnDefinition = Struct.new(:column) # :nodoc:
69
+
70
+ ChangeColumnDefinition = Struct.new(:column, :name) #:nodoc:
71
+
72
+ PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
73
+
74
+ ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do #:nodoc:
75
+ def name
76
+ options[:name]
77
+ end
78
+
79
+ def column
80
+ options[:column]
81
+ end
82
+
83
+ def primary_key
84
+ options[:primary_key] || default_primary_key
85
+ end
86
+
87
+ def on_delete
88
+ options[:on_delete]
89
+ end
90
+
91
+ def on_update
92
+ options[:on_update]
93
+ end
94
+
95
+ def custom_primary_key?
96
+ options[:primary_key] != default_primary_key
97
+ end
98
+
99
+ def validate?
100
+ options.fetch(:validate, true)
101
+ end
102
+ alias validated? validate?
103
+
104
+ def export_name_on_schema_dump?
105
+ !ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
106
+ end
107
+
108
+ def defined_for?(to_table: nil, **options)
109
+ (to_table.nil? || to_table.to_s == self.to_table) &&
110
+ options.all? { |k, v| self.options[k].to_s == v.to_s }
111
+ end
112
+
113
+ private
114
+ def default_primary_key
115
+ "id"
116
+ end
117
+ end
118
+
119
+ class ReferenceDefinition # :nodoc:
120
+ def initialize(
121
+ name,
122
+ polymorphic: false,
123
+ index: true,
124
+ foreign_key: false,
125
+ type: :bigint,
126
+ **options
127
+ )
128
+ @name = name
129
+ @polymorphic = polymorphic
130
+ @index = index
131
+ @foreign_key = foreign_key
132
+ @type = type
133
+ @options = options
134
+
135
+ if polymorphic && foreign_key
136
+ raise ArgumentError, "Cannot add a foreign key to a polymorphic relation"
137
+ end
138
+ end
139
+
140
+ def add_to(table)
141
+ columns.each do |column_options|
142
+ table.column(*column_options)
143
+ end
144
+
145
+ if index
146
+ table.index(column_names, index_options)
147
+ end
148
+
149
+ if foreign_key
150
+ table.foreign_key(foreign_table_name, foreign_key_options)
151
+ end
152
+ end
153
+
154
+ private
155
+ attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
156
+
157
+ def as_options(value)
158
+ value.is_a?(Hash) ? value : {}
159
+ end
160
+
161
+ def polymorphic_options
162
+ as_options(polymorphic).merge(options.slice(:null, :first, :after))
163
+ end
164
+
165
+ def index_options
166
+ as_options(index)
167
+ end
168
+
169
+ def foreign_key_options
170
+ as_options(foreign_key).merge(column: column_name)
171
+ end
172
+
173
+ def columns
174
+ result = [[column_name, type, options]]
175
+ if polymorphic
176
+ result.unshift(["#{name}_type", :string, polymorphic_options])
177
+ end
178
+ result
179
+ end
180
+
181
+ def column_name
182
+ "#{name}_id"
183
+ end
184
+
185
+ def column_names
186
+ columns.map(&:first)
187
+ end
188
+
189
+ def foreign_table_name
190
+ foreign_key_options.fetch(:to_table) do
191
+ Base.pluralize_table_names ? name.to_s.pluralize : name
192
+ end
193
+ end
194
+ end
195
+
196
+ module ColumnMethods
197
+ extend ActiveSupport::Concern
198
+
199
+ # Appends a primary key definition to the table definition.
200
+ # Can be called multiple times, but this is probably not a good idea.
201
+ def primary_key(name, type = :primary_key, **options)
202
+ column(name, type, options.merge(primary_key: true))
203
+ end
204
+
205
+ ##
206
+ # :method: column
207
+ # :call-seq: column(name, type, **options)
208
+ #
209
+ # Appends a column or columns of a specified type.
210
+ #
211
+ # t.string(:goat)
212
+ # t.string(:goat, :sheep)
213
+ #
214
+ # See TableDefinition#column
215
+
216
+ included do
217
+ define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
218
+ :float, :integer, :json, :string, :text, :time, :timestamp, :virtual
219
+
220
+ alias :numeric :decimal
221
+ end
222
+
223
+ class_methods do
224
+ private def define_column_methods(*column_types) # :nodoc:
225
+ column_types.each do |column_type|
226
+ module_eval <<-RUBY, __FILE__, __LINE__ + 1
227
+ def #{column_type}(*names, **options)
228
+ raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
229
+ names.each { |name| column(name, :#{column_type}, options) }
230
+ end
231
+ RUBY
232
+ end
233
+ end
234
+ end
235
+ end
236
+
237
+ # Represents the schema of an SQL table in an abstract way. This class
238
+ # provides methods for manipulating the schema representation.
239
+ #
240
+ # Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
241
+ # is actually of this type:
242
+ #
243
+ # class SomeMigration < ActiveRecord::Migration[5.0]
244
+ # def up
245
+ # create_table :foo do |t|
246
+ # puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
247
+ # end
248
+ # end
249
+ #
250
+ # def down
251
+ # ...
252
+ # end
253
+ # end
254
+ #
255
+ class TableDefinition
256
+ include ColumnMethods
257
+
258
+ attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys
259
+
260
+ def initialize(
261
+ conn,
262
+ name,
263
+ temporary: false,
264
+ if_not_exists: false,
265
+ options: nil,
266
+ as: nil,
267
+ comment: nil,
268
+ **
269
+ )
270
+ @conn = conn
271
+ @columns_hash = {}
272
+ @indexes = []
273
+ @foreign_keys = []
274
+ @primary_keys = nil
275
+ @temporary = temporary
276
+ @if_not_exists = if_not_exists
277
+ @options = options
278
+ @as = as
279
+ @name = name
280
+ @comment = comment
281
+ end
282
+
283
+ def primary_keys(name = nil) # :nodoc:
284
+ @primary_keys = PrimaryKeyDefinition.new(name) if name
285
+ @primary_keys
286
+ end
287
+
288
+ # Returns an array of ColumnDefinition objects for the columns of the table.
289
+ def columns; @columns_hash.values; end
290
+
291
+ # Returns a ColumnDefinition for the column with name +name+.
292
+ def [](name)
293
+ @columns_hash[name.to_s]
294
+ end
295
+
296
+ # Instantiates a new column for the table.
297
+ # See {connection.add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column]
298
+ # for available options.
299
+ #
300
+ # Additional options are:
301
+ # * <tt>:index</tt> -
302
+ # Create an index for the column. Can be either <tt>true</tt> or an options hash.
303
+ #
304
+ # This method returns <tt>self</tt>.
305
+ #
306
+ # == Examples
307
+ #
308
+ # # Assuming +td+ is an instance of TableDefinition
309
+ # td.column(:granted, :boolean, index: true)
310
+ #
311
+ # == Short-hand examples
312
+ #
313
+ # Instead of calling #column directly, you can also work with the short-hand definitions for the default types.
314
+ # They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
315
+ # in a single statement.
316
+ #
317
+ # What can be written like this with the regular calls to column:
318
+ #
319
+ # create_table :products do |t|
320
+ # t.column :shop_id, :integer
321
+ # t.column :creator_id, :integer
322
+ # t.column :item_number, :string
323
+ # t.column :name, :string, default: "Untitled"
324
+ # t.column :value, :string, default: "Untitled"
325
+ # t.column :created_at, :datetime
326
+ # t.column :updated_at, :datetime
327
+ # end
328
+ # add_index :products, :item_number
329
+ #
330
+ # can also be written as follows using the short-hand:
331
+ #
332
+ # create_table :products do |t|
333
+ # t.integer :shop_id, :creator_id
334
+ # t.string :item_number, index: true
335
+ # t.string :name, :value, default: "Untitled"
336
+ # t.timestamps null: false
337
+ # end
338
+ #
339
+ # There's a short-hand method for each of the type values declared at the top. And then there's
340
+ # TableDefinition#timestamps that'll add +created_at+ and +updated_at+ as datetimes.
341
+ #
342
+ # TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
343
+ # column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
344
+ # options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
345
+ # will also create an index, similar to calling {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index].
346
+ # So what can be written like this:
347
+ #
348
+ # create_table :taggings do |t|
349
+ # t.integer :tag_id, :tagger_id, :taggable_id
350
+ # t.string :tagger_type
351
+ # t.string :taggable_type, default: 'Photo'
352
+ # end
353
+ # add_index :taggings, :tag_id, name: 'index_taggings_on_tag_id'
354
+ # add_index :taggings, [:tagger_id, :tagger_type]
355
+ #
356
+ # Can also be written as follows using references:
357
+ #
358
+ # create_table :taggings do |t|
359
+ # t.references :tag, index: { name: 'index_taggings_on_tag_id' }
360
+ # t.references :tagger, polymorphic: true
361
+ # t.references :taggable, polymorphic: { default: 'Photo' }, index: false
362
+ # end
363
+ def column(name, type, **options)
364
+ name = name.to_s
365
+ type = type.to_sym if type
366
+ options = options.dup
367
+
368
+ if @columns_hash[name]
369
+ if @columns_hash[name].primary_key?
370
+ raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
371
+ else
372
+ raise ArgumentError, "you can't define an already defined column '#{name}'."
373
+ end
374
+ end
375
+
376
+ index_options = options.delete(:index)
377
+ index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
378
+ @columns_hash[name] = new_column_definition(name, type, options)
379
+ self
380
+ end
381
+
382
+ # remove the column +name+ from the table.
383
+ # remove_column(:account_id)
384
+ def remove_column(name)
385
+ @columns_hash.delete name.to_s
386
+ end
387
+
388
+ # Adds index options to the indexes hash, keyed by column name
389
+ # This is primarily used to track indexes that need to be created after the table
390
+ #
391
+ # index(:account_id, name: 'index_projects_on_account_id')
392
+ def index(column_name, options = {})
393
+ indexes << [column_name, options]
394
+ end
395
+
396
+ def foreign_key(table_name, options = {}) # :nodoc:
397
+ foreign_keys << [table_name, options]
398
+ end
399
+
400
+ # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
401
+ # <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
402
+ #
403
+ # t.timestamps null: false
404
+ def timestamps(**options)
405
+ options[:null] = false if options[:null].nil?
406
+
407
+ if !options.key?(:precision) && @conn.supports_datetime_with_precision?
408
+ options[:precision] = 6
409
+ end
410
+
411
+ column(:created_at, :datetime, options)
412
+ column(:updated_at, :datetime, options)
413
+ end
414
+
415
+ # Adds a reference.
416
+ #
417
+ # t.references(:user)
418
+ # t.belongs_to(:supplier, foreign_key: true)
419
+ # t.belongs_to(:supplier, foreign_key: true, type: :integer)
420
+ #
421
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
422
+ def references(*args, **options)
423
+ args.each do |ref_name|
424
+ ReferenceDefinition.new(ref_name, options).add_to(self)
425
+ end
426
+ end
427
+ alias :belongs_to :references
428
+
429
+ def new_column_definition(name, type, **options) # :nodoc:
430
+ if integer_like_primary_key?(type, options)
431
+ type = integer_like_primary_key_type(type, options)
432
+ end
433
+ type = aliased_types(type.to_s, type)
434
+ options[:primary_key] ||= type == :primary_key
435
+ options[:null] = false if options[:primary_key]
436
+ create_column_definition(name, type, options)
437
+ end
438
+
439
+ private
440
+ def create_column_definition(name, type, options)
441
+ ColumnDefinition.new(name, type, options)
442
+ end
443
+
444
+ def aliased_types(name, fallback)
445
+ "timestamp" == name ? :datetime : fallback
446
+ end
447
+
448
+ def integer_like_primary_key?(type, options)
449
+ options[:primary_key] && [:integer, :bigint].include?(type) && !options.key?(:default)
450
+ end
451
+
452
+ def integer_like_primary_key_type(type, options)
453
+ type
454
+ end
455
+ end
456
+
457
+ class AlterTable # :nodoc:
458
+ attr_reader :adds
459
+ attr_reader :foreign_key_adds
460
+ attr_reader :foreign_key_drops
461
+
462
+ def initialize(td)
463
+ @td = td
464
+ @adds = []
465
+ @foreign_key_adds = []
466
+ @foreign_key_drops = []
467
+ end
468
+
469
+ def name; @td.name; end
470
+
471
+ def add_foreign_key(to_table, options)
472
+ @foreign_key_adds << ForeignKeyDefinition.new(name, to_table, options)
473
+ end
474
+
475
+ def drop_foreign_key(name)
476
+ @foreign_key_drops << name
477
+ end
478
+
479
+ def add_column(name, type, options)
480
+ name = name.to_s
481
+ type = type.to_sym
482
+ @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, options))
483
+ end
484
+ end
485
+
486
+ # Represents an SQL table in an abstract way for updating a table.
487
+ # Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
488
+ #
489
+ # Available transformations are:
490
+ #
491
+ # change_table :table do |t|
492
+ # t.primary_key
493
+ # t.column
494
+ # t.index
495
+ # t.rename_index
496
+ # t.timestamps
497
+ # t.change
498
+ # t.change_default
499
+ # t.rename
500
+ # t.references
501
+ # t.belongs_to
502
+ # t.string
503
+ # t.text
504
+ # t.integer
505
+ # t.bigint
506
+ # t.float
507
+ # t.decimal
508
+ # t.numeric
509
+ # t.datetime
510
+ # t.timestamp
511
+ # t.time
512
+ # t.date
513
+ # t.binary
514
+ # t.boolean
515
+ # t.foreign_key
516
+ # t.json
517
+ # t.virtual
518
+ # t.remove
519
+ # t.remove_foreign_key
520
+ # t.remove_references
521
+ # t.remove_belongs_to
522
+ # t.remove_index
523
+ # t.remove_timestamps
524
+ # end
525
+ #
526
+ class Table
527
+ include ColumnMethods
528
+
529
+ attr_reader :name
530
+
531
+ def initialize(table_name, base)
532
+ @name = table_name
533
+ @base = base
534
+ end
535
+
536
+ # Adds a new column to the named table.
537
+ #
538
+ # t.column(:name, :string)
539
+ #
540
+ # See TableDefinition#column for details of the options you can use.
541
+ def column(column_name, type, **options)
542
+ index_options = options.delete(:index)
543
+ @base.add_column(name, column_name, type, options)
544
+ index(column_name, index_options.is_a?(Hash) ? index_options : {}) if index_options
545
+ end
546
+
547
+ # Checks to see if a column exists.
548
+ #
549
+ # t.string(:name) unless t.column_exists?(:name, :string)
550
+ #
551
+ # See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
552
+ def column_exists?(column_name, type = nil, options = {})
553
+ @base.column_exists?(name, column_name, type, options)
554
+ end
555
+
556
+ # Adds a new index to the table. +column_name+ can be a single Symbol, or
557
+ # an Array of Symbols.
558
+ #
559
+ # t.index(:name)
560
+ # t.index([:branch_id, :party_id], unique: true)
561
+ # t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
562
+ #
563
+ # See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
564
+ def index(column_name, options = {})
565
+ @base.add_index(name, column_name, options)
566
+ end
567
+
568
+ # Checks to see if an index exists.
569
+ #
570
+ # unless t.index_exists?(:branch_id)
571
+ # t.index(:branch_id)
572
+ # end
573
+ #
574
+ # See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
575
+ def index_exists?(column_name, options = {})
576
+ @base.index_exists?(name, column_name, options)
577
+ end
578
+
579
+ # Renames the given index on the table.
580
+ #
581
+ # t.rename_index(:user_id, :account_id)
582
+ #
583
+ # See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index]
584
+ def rename_index(index_name, new_index_name)
585
+ @base.rename_index(name, index_name, new_index_name)
586
+ end
587
+
588
+ # Adds timestamps (+created_at+ and +updated_at+) columns to the table.
589
+ #
590
+ # t.timestamps(null: false)
591
+ #
592
+ # See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
593
+ def timestamps(options = {})
594
+ @base.add_timestamps(name, options)
595
+ end
596
+
597
+ # Changes the column's definition according to the new options.
598
+ #
599
+ # t.change(:name, :string, limit: 80)
600
+ # t.change(:description, :text)
601
+ #
602
+ # See TableDefinition#column for details of the options you can use.
603
+ def change(column_name, type, options = {})
604
+ @base.change_column(name, column_name, type, options)
605
+ end
606
+
607
+ # Sets a new default value for a column.
608
+ #
609
+ # t.change_default(:qualification, 'new')
610
+ # t.change_default(:authorized, 1)
611
+ # t.change_default(:status, from: nil, to: "draft")
612
+ #
613
+ # See {connection.change_column_default}[rdoc-ref:SchemaStatements#change_column_default]
614
+ def change_default(column_name, default_or_changes)
615
+ @base.change_column_default(name, column_name, default_or_changes)
616
+ end
617
+
618
+ # Removes the column(s) from the table definition.
619
+ #
620
+ # t.remove(:qualification)
621
+ # t.remove(:qualification, :experience)
622
+ #
623
+ # See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
624
+ def remove(*column_names)
625
+ @base.remove_columns(name, *column_names)
626
+ end
627
+
628
+ # Removes the given index from the table.
629
+ #
630
+ # t.remove_index(:branch_id)
631
+ # t.remove_index(column: [:branch_id, :party_id])
632
+ # t.remove_index(name: :by_branch_party)
633
+ #
634
+ # See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
635
+ def remove_index(options = {})
636
+ @base.remove_index(name, options)
637
+ end
638
+
639
+ # Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
640
+ #
641
+ # t.remove_timestamps
642
+ #
643
+ # See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
644
+ def remove_timestamps(options = {})
645
+ @base.remove_timestamps(name, options)
646
+ end
647
+
648
+ # Renames a column.
649
+ #
650
+ # t.rename(:description, :name)
651
+ #
652
+ # See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column]
653
+ def rename(column_name, new_column_name)
654
+ @base.rename_column(name, column_name, new_column_name)
655
+ end
656
+
657
+ # Adds a reference.
658
+ #
659
+ # t.references(:user)
660
+ # t.belongs_to(:supplier, foreign_key: true)
661
+ #
662
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
663
+ def references(*args, **options)
664
+ args.each do |ref_name|
665
+ @base.add_reference(name, ref_name, options)
666
+ end
667
+ end
668
+ alias :belongs_to :references
669
+
670
+ # Removes a reference. Optionally removes a +type+ column.
671
+ #
672
+ # t.remove_references(:user)
673
+ # t.remove_belongs_to(:supplier, polymorphic: true)
674
+ #
675
+ # See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
676
+ def remove_references(*args, **options)
677
+ args.each do |ref_name|
678
+ @base.remove_reference(name, ref_name, options)
679
+ end
680
+ end
681
+ alias :remove_belongs_to :remove_references
682
+
683
+ # Adds a foreign key to the table using a supplied table name.
684
+ #
685
+ # t.foreign_key(:authors)
686
+ # t.foreign_key(:authors, column: :author_id, primary_key: "id")
687
+ #
688
+ # See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
689
+ def foreign_key(*args)
690
+ @base.add_foreign_key(name, *args)
691
+ end
692
+
693
+ # Removes the given foreign key from the table.
694
+ #
695
+ # t.remove_foreign_key(:authors)
696
+ # t.remove_foreign_key(column: :author_id)
697
+ #
698
+ # See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
699
+ def remove_foreign_key(*args)
700
+ @base.remove_foreign_key(name, *args)
701
+ end
702
+
703
+ # Checks to see if a foreign key exists.
704
+ #
705
+ # t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
706
+ #
707
+ # See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
708
+ def foreign_key_exists?(*args)
709
+ @base.foreign_key_exists?(name, *args)
710
+ end
711
+ end
712
+ end
713
+ end