activerecord 5.2.8.1 → 6.1.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1347 -624
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +9 -8
  7. data/lib/active_record/association_relation.rb +30 -10
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +100 -41
  10. data/lib/active_record/associations/association_scope.rb +23 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +55 -48
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
  13. data/lib/active_record/associations/builder/association.rb +45 -22
  14. data/lib/active_record/associations/builder/belongs_to.rb +29 -59
  15. data/lib/active_record/associations/builder/collection_association.rb +8 -17
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -2
  18. data/lib/active_record/associations/builder/has_one.rb +33 -2
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -1
  20. data/lib/active_record/associations/collection_association.rb +44 -34
  21. data/lib/active_record/associations/collection_proxy.rb +25 -21
  22. data/lib/active_record/associations/foreign_association.rb +20 -0
  23. data/lib/active_record/associations/has_many_association.rb +26 -13
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -18
  25. data/lib/active_record/associations/has_one_association.rb +43 -31
  26. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  27. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  28. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  29. data/lib/active_record/associations/join_dependency.rb +91 -60
  30. data/lib/active_record/associations/preloader/association.rb +69 -43
  31. data/lib/active_record/associations/preloader/through_association.rb +49 -40
  32. data/lib/active_record/associations/preloader.rb +47 -34
  33. data/lib/active_record/associations/singular_association.rb +3 -17
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/associations.rb +137 -25
  36. data/lib/active_record/attribute_assignment.rb +17 -19
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
  38. data/lib/active_record/attribute_methods/dirty.rb +101 -40
  39. data/lib/active_record/attribute_methods/primary_key.rb +20 -25
  40. data/lib/active_record/attribute_methods/query.rb +4 -8
  41. data/lib/active_record/attribute_methods/read.rb +14 -56
  42. data/lib/active_record/attribute_methods/serialization.rb +12 -7
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +18 -34
  45. data/lib/active_record/attribute_methods.rb +81 -143
  46. data/lib/active_record/attributes.rb +46 -9
  47. data/lib/active_record/autosave_association.rb +57 -42
  48. data/lib/active_record/base.rb +4 -17
  49. data/lib/active_record/callbacks.rb +158 -43
  50. data/lib/active_record/coders/yaml_column.rb +16 -7
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +107 -47
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
  64. data/lib/active_record/connection_adapters/column.rb +30 -12
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  67. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +88 -32
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
  77. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
  81. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  93. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  94. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  96. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  97. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/quoting.rb +73 -10
  99. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  100. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
  101. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  102. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  103. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
  104. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  105. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  106. data/lib/active_record/connection_adapters/postgresql_adapter.rb +225 -121
  107. data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
  108. data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
  109. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  110. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  111. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  112. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
  113. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
  114. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  115. data/lib/active_record/connection_adapters.rb +52 -0
  116. data/lib/active_record/connection_handling.rb +293 -33
  117. data/lib/active_record/core.rb +341 -99
  118. data/lib/active_record/counter_cache.rb +8 -30
  119. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  120. data/lib/active_record/database_configurations/database_config.rb +80 -0
  121. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  122. data/lib/active_record/database_configurations/url_config.rb +53 -0
  123. data/lib/active_record/database_configurations.rb +273 -0
  124. data/lib/active_record/delegated_type.rb +209 -0
  125. data/lib/active_record/destroy_association_async_job.rb +36 -0
  126. data/lib/active_record/dynamic_matchers.rb +3 -4
  127. data/lib/active_record/enum.rb +108 -36
  128. data/lib/active_record/errors.rb +62 -19
  129. data/lib/active_record/explain.rb +10 -6
  130. data/lib/active_record/explain_subscriber.rb +1 -1
  131. data/lib/active_record/fixture_set/file.rb +10 -17
  132. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  133. data/lib/active_record/fixture_set/render_context.rb +17 -0
  134. data/lib/active_record/fixture_set/table_row.rb +152 -0
  135. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  136. data/lib/active_record/fixtures.rb +200 -481
  137. data/lib/active_record/gem_version.rb +4 -4
  138. data/lib/active_record/inheritance.rb +53 -24
  139. data/lib/active_record/insert_all.rb +212 -0
  140. data/lib/active_record/integration.rb +67 -17
  141. data/lib/active_record/internal_metadata.rb +28 -9
  142. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  143. data/lib/active_record/locking/optimistic.rb +37 -23
  144. data/lib/active_record/locking/pessimistic.rb +9 -5
  145. data/lib/active_record/log_subscriber.rb +35 -35
  146. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  147. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  148. data/lib/active_record/middleware/database_selector.rb +77 -0
  149. data/lib/active_record/migration/command_recorder.rb +96 -44
  150. data/lib/active_record/migration/compatibility.rb +145 -64
  151. data/lib/active_record/migration/join_table.rb +0 -1
  152. data/lib/active_record/migration.rb +206 -157
  153. data/lib/active_record/model_schema.rb +148 -22
  154. data/lib/active_record/nested_attributes.rb +4 -7
  155. data/lib/active_record/no_touching.rb +8 -1
  156. data/lib/active_record/null_relation.rb +0 -1
  157. data/lib/active_record/persistence.rb +267 -59
  158. data/lib/active_record/query_cache.rb +21 -4
  159. data/lib/active_record/querying.rb +40 -23
  160. data/lib/active_record/railtie.rb +113 -74
  161. data/lib/active_record/railties/console_sandbox.rb +2 -4
  162. data/lib/active_record/railties/controller_runtime.rb +30 -35
  163. data/lib/active_record/railties/databases.rake +411 -80
  164. data/lib/active_record/readonly_attributes.rb +4 -0
  165. data/lib/active_record/reflection.rb +109 -93
  166. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  167. data/lib/active_record/relation/batches.rb +44 -35
  168. data/lib/active_record/relation/calculations.rb +157 -90
  169. data/lib/active_record/relation/delegation.rb +35 -50
  170. data/lib/active_record/relation/finder_methods.rb +64 -39
  171. data/lib/active_record/relation/from_clause.rb +5 -1
  172. data/lib/active_record/relation/merger.rb +32 -40
  173. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  174. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  179. data/lib/active_record/relation/predicate_builder.rb +62 -45
  180. data/lib/active_record/relation/query_attribute.rb +13 -8
  181. data/lib/active_record/relation/query_methods.rb +478 -187
  182. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  183. data/lib/active_record/relation/spawn_methods.rb +9 -9
  184. data/lib/active_record/relation/where_clause.rb +115 -62
  185. data/lib/active_record/relation.rb +379 -115
  186. data/lib/active_record/result.rb +64 -38
  187. data/lib/active_record/runtime_registry.rb +2 -2
  188. data/lib/active_record/sanitization.rb +22 -41
  189. data/lib/active_record/schema.rb +2 -11
  190. data/lib/active_record/schema_dumper.rb +54 -9
  191. data/lib/active_record/schema_migration.rb +7 -9
  192. data/lib/active_record/scoping/default.rb +4 -8
  193. data/lib/active_record/scoping/named.rb +17 -24
  194. data/lib/active_record/scoping.rb +8 -9
  195. data/lib/active_record/secure_token.rb +16 -8
  196. data/lib/active_record/serialization.rb +5 -3
  197. data/lib/active_record/signed_id.rb +116 -0
  198. data/lib/active_record/statement_cache.rb +49 -6
  199. data/lib/active_record/store.rb +94 -10
  200. data/lib/active_record/suppressor.rb +2 -2
  201. data/lib/active_record/table_metadata.rb +42 -43
  202. data/lib/active_record/tasks/database_tasks.rb +277 -81
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  206. data/lib/active_record/test_databases.rb +24 -0
  207. data/lib/active_record/test_fixtures.rb +291 -0
  208. data/lib/active_record/timestamp.rb +43 -32
  209. data/lib/active_record/touch_later.rb +23 -22
  210. data/lib/active_record/transactions.rb +62 -118
  211. data/lib/active_record/translation.rb +1 -1
  212. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  213. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  214. data/lib/active_record/type/serialized.rb +6 -3
  215. data/lib/active_record/type/time.rb +10 -0
  216. data/lib/active_record/type/type_map.rb +0 -1
  217. data/lib/active_record/type/unsigned_integer.rb +0 -1
  218. data/lib/active_record/type.rb +10 -5
  219. data/lib/active_record/type_caster/connection.rb +15 -15
  220. data/lib/active_record/type_caster/map.rb +8 -8
  221. data/lib/active_record/validations/associated.rb +1 -2
  222. data/lib/active_record/validations/numericality.rb +35 -0
  223. data/lib/active_record/validations/uniqueness.rb +38 -30
  224. data/lib/active_record/validations.rb +4 -3
  225. data/lib/active_record.rb +13 -12
  226. data/lib/arel/alias_predication.rb +9 -0
  227. data/lib/arel/attributes/attribute.rb +41 -0
  228. data/lib/arel/collectors/bind.rb +29 -0
  229. data/lib/arel/collectors/composite.rb +39 -0
  230. data/lib/arel/collectors/plain_string.rb +20 -0
  231. data/lib/arel/collectors/sql_string.rb +27 -0
  232. data/lib/arel/collectors/substitute_binds.rb +35 -0
  233. data/lib/arel/crud.rb +42 -0
  234. data/lib/arel/delete_manager.rb +18 -0
  235. data/lib/arel/errors.rb +9 -0
  236. data/lib/arel/expressions.rb +29 -0
  237. data/lib/arel/factory_methods.rb +49 -0
  238. data/lib/arel/insert_manager.rb +49 -0
  239. data/lib/arel/math.rb +45 -0
  240. data/lib/arel/nodes/and.rb +32 -0
  241. data/lib/arel/nodes/ascending.rb +23 -0
  242. data/lib/arel/nodes/binary.rb +126 -0
  243. data/lib/arel/nodes/bind_param.rb +44 -0
  244. data/lib/arel/nodes/case.rb +55 -0
  245. data/lib/arel/nodes/casted.rb +62 -0
  246. data/lib/arel/nodes/comment.rb +29 -0
  247. data/lib/arel/nodes/count.rb +12 -0
  248. data/lib/arel/nodes/delete_statement.rb +45 -0
  249. data/lib/arel/nodes/descending.rb +23 -0
  250. data/lib/arel/nodes/equality.rb +15 -0
  251. data/lib/arel/nodes/extract.rb +24 -0
  252. data/lib/arel/nodes/false.rb +16 -0
  253. data/lib/arel/nodes/full_outer_join.rb +8 -0
  254. data/lib/arel/nodes/function.rb +44 -0
  255. data/lib/arel/nodes/grouping.rb +11 -0
  256. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  257. data/lib/arel/nodes/in.rb +15 -0
  258. data/lib/arel/nodes/infix_operation.rb +92 -0
  259. data/lib/arel/nodes/inner_join.rb +8 -0
  260. data/lib/arel/nodes/insert_statement.rb +37 -0
  261. data/lib/arel/nodes/join_source.rb +20 -0
  262. data/lib/arel/nodes/matches.rb +18 -0
  263. data/lib/arel/nodes/named_function.rb +23 -0
  264. data/lib/arel/nodes/node.rb +51 -0
  265. data/lib/arel/nodes/node_expression.rb +13 -0
  266. data/lib/arel/nodes/ordering.rb +27 -0
  267. data/lib/arel/nodes/outer_join.rb +8 -0
  268. data/lib/arel/nodes/over.rb +15 -0
  269. data/lib/arel/nodes/regexp.rb +16 -0
  270. data/lib/arel/nodes/right_outer_join.rb +8 -0
  271. data/lib/arel/nodes/select_core.rb +67 -0
  272. data/lib/arel/nodes/select_statement.rb +41 -0
  273. data/lib/arel/nodes/sql_literal.rb +19 -0
  274. data/lib/arel/nodes/string_join.rb +11 -0
  275. data/lib/arel/nodes/table_alias.rb +31 -0
  276. data/lib/arel/nodes/terminal.rb +16 -0
  277. data/lib/arel/nodes/true.rb +16 -0
  278. data/lib/arel/nodes/unary.rb +44 -0
  279. data/lib/arel/nodes/unary_operation.rb +20 -0
  280. data/lib/arel/nodes/unqualified_column.rb +22 -0
  281. data/lib/arel/nodes/update_statement.rb +41 -0
  282. data/lib/arel/nodes/values_list.rb +9 -0
  283. data/lib/arel/nodes/window.rb +126 -0
  284. data/lib/arel/nodes/with.rb +11 -0
  285. data/lib/arel/nodes.rb +70 -0
  286. data/lib/arel/order_predications.rb +13 -0
  287. data/lib/arel/predications.rb +250 -0
  288. data/lib/arel/select_manager.rb +270 -0
  289. data/lib/arel/table.rb +118 -0
  290. data/lib/arel/tree_manager.rb +72 -0
  291. data/lib/arel/update_manager.rb +34 -0
  292. data/lib/arel/visitors/dot.rb +308 -0
  293. data/lib/arel/visitors/mysql.rb +93 -0
  294. data/lib/arel/visitors/postgresql.rb +120 -0
  295. data/lib/arel/visitors/sqlite.rb +38 -0
  296. data/lib/arel/visitors/to_sql.rb +899 -0
  297. data/lib/arel/visitors/visitor.rb +45 -0
  298. data/lib/arel/visitors.rb +13 -0
  299. data/lib/arel/window_predications.rb +9 -0
  300. data/lib/arel.rb +54 -0
  301. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  302. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  303. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  304. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  305. data/lib/rails/generators/active_record/migration.rb +19 -2
  306. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  307. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  308. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  309. metadata +118 -32
  310. data/lib/active_record/attribute_decorators.rb +0 -90
  311. data/lib/active_record/collection_cache_key.rb +0 -53
  312. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  313. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  314. data/lib/active_record/define_callbacks.rb +0 -22
  315. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  316. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -33,6 +33,14 @@ module ActiveRecord
33
33
  @comment = comment
34
34
  end
35
35
 
36
+ def column_options
37
+ {
38
+ length: lengths,
39
+ order: orders,
40
+ opclass: opclasses,
41
+ }
42
+ end
43
+
36
44
  private
37
45
  def concise_options(options)
38
46
  if columns.size == options.size && options.values.uniq.size == 1
@@ -63,12 +71,18 @@ module ActiveRecord
63
71
  end
64
72
  CODE
65
73
  end
74
+
75
+ def aliased_types(name, fallback)
76
+ "timestamp" == name ? :datetime : fallback
77
+ end
66
78
  end
67
79
 
68
80
  AddColumnDefinition = Struct.new(:column) # :nodoc:
69
81
 
70
82
  ChangeColumnDefinition = Struct.new(:column, :name) #:nodoc:
71
83
 
84
+ CreateIndexDefinition = Struct.new(:index, :algorithm, :if_not_exists) # :nodoc:
85
+
72
86
  PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
73
87
 
74
88
  ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do #:nodoc:
@@ -101,13 +115,14 @@ module ActiveRecord
101
115
  end
102
116
  alias validated? validate?
103
117
 
104
- def defined_for?(to_table_ord = nil, to_table: nil, **options)
105
- if to_table_ord
106
- self.to_table == to_table_ord.to_s
107
- else
108
- (to_table.nil? || to_table.to_s == self.to_table) &&
109
- options.all? { |k, v| self.options[k].to_s == v.to_s }
110
- end
118
+ def export_name_on_schema_dump?
119
+ !ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
120
+ end
121
+
122
+ def defined_for?(to_table: nil, validate: nil, **options)
123
+ (to_table.nil? || to_table.to_s == self.to_table) &&
124
+ (validate.nil? || validate == options.fetch(:validate, validate)) &&
125
+ options.all? { |k, v| self.options[k].to_s == v.to_s }
111
126
  end
112
127
 
113
128
  private
@@ -116,6 +131,21 @@ module ActiveRecord
116
131
  end
117
132
  end
118
133
 
134
+ CheckConstraintDefinition = Struct.new(:table_name, :expression, :options) do
135
+ def name
136
+ options[:name]
137
+ end
138
+
139
+ def validate?
140
+ options.fetch(:validate, true)
141
+ end
142
+ alias validated? validate?
143
+
144
+ def export_name_on_schema_dump?
145
+ !ActiveRecord::SchemaDumper.chk_ignore_pattern.match?(name) if name
146
+ end
147
+ end
148
+
119
149
  class ReferenceDefinition # :nodoc:
120
150
  def initialize(
121
151
  name,
@@ -138,26 +168,21 @@ module ActiveRecord
138
168
  end
139
169
 
140
170
  def add_to(table)
141
- columns.each do |column_options|
142
- table.column(*column_options)
171
+ columns.each do |name, type, options|
172
+ table.column(name, type, **options)
143
173
  end
144
174
 
145
175
  if index
146
- table.index(column_names, index_options)
176
+ table.index(column_names, **index_options(table.name))
147
177
  end
148
178
 
149
179
  if foreign_key
150
- table.foreign_key(foreign_table_name, foreign_key_options)
180
+ table.foreign_key(foreign_table_name, **foreign_key_options)
151
181
  end
152
182
  end
153
183
 
154
- # TODO Change this to private once we've dropped Ruby 2.2 support.
155
- # Workaround for Ruby 2.2 "private attribute?" warning.
156
- protected
157
-
158
- attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
159
-
160
184
  private
185
+ attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
161
186
 
162
187
  def as_options(value)
163
188
  value.is_a?(Hash) ? value : {}
@@ -167,8 +192,18 @@ module ActiveRecord
167
192
  as_options(polymorphic).merge(options.slice(:null, :first, :after))
168
193
  end
169
194
 
170
- def index_options
171
- as_options(index)
195
+ def polymorphic_index_name(table_name)
196
+ "index_#{table_name}_on_#{name}"
197
+ end
198
+
199
+ def index_options(table_name)
200
+ index_options = as_options(index)
201
+
202
+ # legacy reference index names are used on versions 6.0 and earlier
203
+ return index_options if options[:_uses_legacy_reference_index_name]
204
+
205
+ index_options[:name] ||= polymorphic_index_name(table_name) if polymorphic
206
+ index_options
172
207
  end
173
208
 
174
209
  def foreign_key_options
@@ -199,41 +234,45 @@ module ActiveRecord
199
234
  end
200
235
 
201
236
  module ColumnMethods
237
+ extend ActiveSupport::Concern
238
+
202
239
  # Appends a primary key definition to the table definition.
203
240
  # Can be called multiple times, but this is probably not a good idea.
204
241
  def primary_key(name, type = :primary_key, **options)
205
- column(name, type, options.merge(primary_key: true))
242
+ column(name, type, **options.merge(primary_key: true))
206
243
  end
207
244
 
245
+ ##
246
+ # :method: column
247
+ # :call-seq: column(name, type, **options)
248
+ #
208
249
  # Appends a column or columns of a specified type.
209
250
  #
210
251
  # t.string(:goat)
211
252
  # t.string(:goat, :sheep)
212
253
  #
213
254
  # See TableDefinition#column
214
- [
215
- :bigint,
216
- :binary,
217
- :boolean,
218
- :date,
219
- :datetime,
220
- :decimal,
221
- :float,
222
- :integer,
223
- :json,
224
- :string,
225
- :text,
226
- :time,
227
- :timestamp,
228
- :virtual,
229
- ].each do |column_type|
230
- module_eval <<-CODE, __FILE__, __LINE__ + 1
231
- def #{column_type}(*args, **options)
232
- args.each { |name| column(name, :#{column_type}, options) }
255
+
256
+ included do
257
+ define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
258
+ :float, :integer, :json, :string, :text, :time, :timestamp, :virtual
259
+
260
+ alias :numeric :decimal
261
+ end
262
+
263
+ class_methods do
264
+ def define_column_methods(*column_types) # :nodoc:
265
+ column_types.each do |column_type|
266
+ module_eval <<-RUBY, __FILE__, __LINE__ + 1
267
+ def #{column_type}(*names, **options)
268
+ raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
269
+ names.each { |name| column(name, :#{column_type}, **options) }
270
+ end
271
+ RUBY
233
272
  end
234
- CODE
273
+ end
274
+ private :define_column_methods
235
275
  end
236
- alias_method :numeric, :decimal
237
276
  end
238
277
 
239
278
  # Represents the schema of an SQL table in an abstract way. This class
@@ -242,7 +281,7 @@ module ActiveRecord
242
281
  # Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
243
282
  # is actually of this type:
244
283
  #
245
- # class SomeMigration < ActiveRecord::Migration[5.0]
284
+ # class SomeMigration < ActiveRecord::Migration[6.0]
246
285
  # def up
247
286
  # create_table :foo do |t|
248
287
  # puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
@@ -257,15 +296,26 @@ module ActiveRecord
257
296
  class TableDefinition
258
297
  include ColumnMethods
259
298
 
260
- attr_accessor :indexes
261
- attr_reader :name, :temporary, :options, :as, :foreign_keys, :comment
299
+ attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys, :check_constraints
262
300
 
263
- def initialize(name, temporary = false, options = nil, as = nil, comment: nil)
301
+ def initialize(
302
+ conn,
303
+ name,
304
+ temporary: false,
305
+ if_not_exists: false,
306
+ options: nil,
307
+ as: nil,
308
+ comment: nil,
309
+ **
310
+ )
311
+ @conn = conn
264
312
  @columns_hash = {}
265
313
  @indexes = []
266
314
  @foreign_keys = []
267
315
  @primary_keys = nil
316
+ @check_constraints = []
268
317
  @temporary = temporary
318
+ @if_not_exists = if_not_exists
269
319
  @options = options
270
320
  @as = as
271
321
  @name = name
@@ -349,21 +399,28 @@ module ActiveRecord
349
399
  #
350
400
  # create_table :taggings do |t|
351
401
  # t.references :tag, index: { name: 'index_taggings_on_tag_id' }
352
- # t.references :tagger, polymorphic: true, index: true
353
- # t.references :taggable, polymorphic: { default: 'Photo' }
402
+ # t.references :tagger, polymorphic: true
403
+ # t.references :taggable, polymorphic: { default: 'Photo' }, index: false
354
404
  # end
355
- def column(name, type, options = {})
405
+ def column(name, type, index: nil, **options)
356
406
  name = name.to_s
357
407
  type = type.to_sym if type
358
- options = options.dup
359
408
 
360
- if @columns_hash[name] && @columns_hash[name].primary_key?
361
- raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
409
+ if @columns_hash[name]
410
+ if @columns_hash[name].primary_key?
411
+ raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
412
+ else
413
+ raise ArgumentError, "you can't define an already defined column '#{name}'."
414
+ end
415
+ end
416
+
417
+ @columns_hash[name] = new_column_definition(name, type, **options)
418
+
419
+ if index
420
+ index_options = index.is_a?(Hash) ? index : {}
421
+ index(name, **index_options)
362
422
  end
363
423
 
364
- index_options = options.delete(:index)
365
- index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
366
- @columns_hash[name] = new_column_definition(name, type, options)
367
424
  self
368
425
  end
369
426
 
@@ -377,15 +434,16 @@ module ActiveRecord
377
434
  # This is primarily used to track indexes that need to be created after the table
378
435
  #
379
436
  # index(:account_id, name: 'index_projects_on_account_id')
380
- def index(column_name, options = {})
437
+ def index(column_name, **options)
381
438
  indexes << [column_name, options]
382
439
  end
383
440
 
384
- def foreign_key(table_name, options = {}) # :nodoc:
385
- table_name_prefix = ActiveRecord::Base.table_name_prefix
386
- table_name_suffix = ActiveRecord::Base.table_name_suffix
387
- table_name = "#{table_name_prefix}#{table_name}#{table_name_suffix}"
388
- foreign_keys.push([table_name, options])
441
+ def foreign_key(table_name, **options) # :nodoc:
442
+ foreign_keys << [table_name, options]
443
+ end
444
+
445
+ def check_constraint(expression, **options)
446
+ check_constraints << [expression, options]
389
447
  end
390
448
 
391
449
  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
@@ -395,19 +453,24 @@ module ActiveRecord
395
453
  def timestamps(**options)
396
454
  options[:null] = false if options[:null].nil?
397
455
 
398
- column(:created_at, :datetime, options)
399
- column(:updated_at, :datetime, options)
456
+ if !options.key?(:precision) && @conn.supports_datetime_with_precision?
457
+ options[:precision] = 6
458
+ end
459
+
460
+ column(:created_at, :datetime, **options)
461
+ column(:updated_at, :datetime, **options)
400
462
  end
401
463
 
402
464
  # Adds a reference.
403
465
  #
404
466
  # t.references(:user)
405
467
  # t.belongs_to(:supplier, foreign_key: true)
468
+ # t.belongs_to(:supplier, foreign_key: true, type: :integer)
406
469
  #
407
470
  # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
408
471
  def references(*args, **options)
409
472
  args.each do |ref_name|
410
- ReferenceDefinition.new(ref_name, options).add_to(self)
473
+ ReferenceDefinition.new(ref_name, **options).add_to(self)
411
474
  end
412
475
  end
413
476
  alias :belongs_to :references
@@ -442,14 +505,16 @@ module ActiveRecord
442
505
 
443
506
  class AlterTable # :nodoc:
444
507
  attr_reader :adds
445
- attr_reader :foreign_key_adds
446
- attr_reader :foreign_key_drops
508
+ attr_reader :foreign_key_adds, :foreign_key_drops
509
+ attr_reader :check_constraint_adds, :check_constraint_drops
447
510
 
448
511
  def initialize(td)
449
512
  @td = td
450
513
  @adds = []
451
514
  @foreign_key_adds = []
452
515
  @foreign_key_drops = []
516
+ @check_constraint_adds = []
517
+ @check_constraint_drops = []
453
518
  end
454
519
 
455
520
  def name; @td.name; end
@@ -462,10 +527,18 @@ module ActiveRecord
462
527
  @foreign_key_drops << name
463
528
  end
464
529
 
465
- def add_column(name, type, options)
530
+ def add_check_constraint(expression, options)
531
+ @check_constraint_adds << CheckConstraintDefinition.new(name, expression, options)
532
+ end
533
+
534
+ def drop_check_constraint(constraint_name)
535
+ @check_constraint_drops << constraint_name
536
+ end
537
+
538
+ def add_column(name, type, **options)
466
539
  name = name.to_s
467
540
  type = type.to_sym
468
- @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, options))
541
+ @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, **options))
469
542
  end
470
543
  end
471
544
 
@@ -482,9 +555,11 @@ module ActiveRecord
482
555
  # t.timestamps
483
556
  # t.change
484
557
  # t.change_default
558
+ # t.change_null
485
559
  # t.rename
486
560
  # t.references
487
561
  # t.belongs_to
562
+ # t.check_constraint
488
563
  # t.string
489
564
  # t.text
490
565
  # t.integer
@@ -502,9 +577,11 @@ module ActiveRecord
502
577
  # t.json
503
578
  # t.virtual
504
579
  # t.remove
580
+ # t.remove_foreign_key
505
581
  # t.remove_references
506
582
  # t.remove_belongs_to
507
583
  # t.remove_index
584
+ # t.remove_check_constraint
508
585
  # t.remove_timestamps
509
586
  # end
510
587
  #
@@ -523,8 +600,12 @@ module ActiveRecord
523
600
  # t.column(:name, :string)
524
601
  #
525
602
  # See TableDefinition#column for details of the options you can use.
526
- def column(column_name, type, options = {})
527
- @base.add_column(name, column_name, type, options)
603
+ def column(column_name, type, index: nil, **options)
604
+ @base.add_column(name, column_name, type, **options)
605
+ if index
606
+ index_options = index.is_a?(Hash) ? index : {}
607
+ index(column_name, **index_options)
608
+ end
528
609
  end
529
610
 
530
611
  # Checks to see if a column exists.
@@ -532,8 +613,8 @@ module ActiveRecord
532
613
  # t.string(:name) unless t.column_exists?(:name, :string)
533
614
  #
534
615
  # See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
535
- def column_exists?(column_name, type = nil, options = {})
536
- @base.column_exists?(name, column_name, type, options)
616
+ def column_exists?(column_name, type = nil, **options)
617
+ @base.column_exists?(name, column_name, type, **options)
537
618
  end
538
619
 
539
620
  # Adds a new index to the table. +column_name+ can be a single Symbol, or
@@ -544,8 +625,8 @@ module ActiveRecord
544
625
  # t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
545
626
  #
546
627
  # See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
547
- def index(column_name, options = {})
548
- @base.add_index(name, column_name, options)
628
+ def index(column_name, **options)
629
+ @base.add_index(name, column_name, **options)
549
630
  end
550
631
 
551
632
  # Checks to see if an index exists.
@@ -573,8 +654,8 @@ module ActiveRecord
573
654
  # t.timestamps(null: false)
574
655
  #
575
656
  # See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
576
- def timestamps(options = {})
577
- @base.add_timestamps(name, options)
657
+ def timestamps(**options)
658
+ @base.add_timestamps(name, **options)
578
659
  end
579
660
 
580
661
  # Changes the column's definition according to the new options.
@@ -583,8 +664,8 @@ module ActiveRecord
583
664
  # t.change(:description, :text)
584
665
  #
585
666
  # See TableDefinition#column for details of the options you can use.
586
- def change(column_name, type, options = {})
587
- @base.change_column(name, column_name, type, options)
667
+ def change(column_name, type, **options)
668
+ @base.change_column(name, column_name, type, **options)
588
669
  end
589
670
 
590
671
  # Sets a new default value for a column.
@@ -598,14 +679,24 @@ module ActiveRecord
598
679
  @base.change_column_default(name, column_name, default_or_changes)
599
680
  end
600
681
 
682
+ # Sets or removes a NOT NULL constraint on a column.
683
+ #
684
+ # t.change_null(:qualification, true)
685
+ # t.change_null(:qualification, false, 0)
686
+ #
687
+ # See {connection.change_column_null}[rdoc-ref:SchemaStatements#change_column_null]
688
+ def change_null(column_name, null, default = nil)
689
+ @base.change_column_null(name, column_name, null, default)
690
+ end
691
+
601
692
  # Removes the column(s) from the table definition.
602
693
  #
603
694
  # t.remove(:qualification)
604
695
  # t.remove(:qualification, :experience)
605
696
  #
606
697
  # See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
607
- def remove(*column_names)
608
- @base.remove_columns(name, *column_names)
698
+ def remove(*column_names, **options)
699
+ @base.remove_columns(name, *column_names, **options)
609
700
  end
610
701
 
611
702
  # Removes the given index from the table.
@@ -613,10 +704,11 @@ module ActiveRecord
613
704
  # t.remove_index(:branch_id)
614
705
  # t.remove_index(column: [:branch_id, :party_id])
615
706
  # t.remove_index(name: :by_branch_party)
707
+ # t.remove_index(:branch_id, name: :by_branch_party)
616
708
  #
617
709
  # See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
618
- def remove_index(options = {})
619
- @base.remove_index(name, options)
710
+ def remove_index(column_name = nil, **options)
711
+ @base.remove_index(name, column_name, **options)
620
712
  end
621
713
 
622
714
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
@@ -624,8 +716,8 @@ module ActiveRecord
624
716
  # t.remove_timestamps
625
717
  #
626
718
  # See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
627
- def remove_timestamps(options = {})
628
- @base.remove_timestamps(name, options)
719
+ def remove_timestamps(**options)
720
+ @base.remove_timestamps(name, **options)
629
721
  end
630
722
 
631
723
  # Renames a column.
@@ -645,7 +737,7 @@ module ActiveRecord
645
737
  # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
646
738
  def references(*args, **options)
647
739
  args.each do |ref_name|
648
- @base.add_reference(name, ref_name, options)
740
+ @base.add_reference(name, ref_name, **options)
649
741
  end
650
742
  end
651
743
  alias :belongs_to :references
@@ -658,18 +750,29 @@ module ActiveRecord
658
750
  # See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
659
751
  def remove_references(*args, **options)
660
752
  args.each do |ref_name|
661
- @base.remove_reference(name, ref_name, options)
753
+ @base.remove_reference(name, ref_name, **options)
662
754
  end
663
755
  end
664
756
  alias :remove_belongs_to :remove_references
665
757
 
666
- # Adds a foreign key.
758
+ # Adds a foreign key to the table using a supplied table name.
667
759
  #
668
760
  # t.foreign_key(:authors)
761
+ # t.foreign_key(:authors, column: :author_id, primary_key: "id")
669
762
  #
670
763
  # See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
671
- def foreign_key(*args)
672
- @base.add_foreign_key(name, *args)
764
+ def foreign_key(*args, **options)
765
+ @base.add_foreign_key(name, *args, **options)
766
+ end
767
+
768
+ # Removes the given foreign key from the table.
769
+ #
770
+ # t.remove_foreign_key(:authors)
771
+ # t.remove_foreign_key(column: :author_id)
772
+ #
773
+ # See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
774
+ def remove_foreign_key(*args, **options)
775
+ @base.remove_foreign_key(name, *args, **options)
673
776
  end
674
777
 
675
778
  # Checks to see if a foreign key exists.
@@ -677,8 +780,26 @@ module ActiveRecord
677
780
  # t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
678
781
  #
679
782
  # See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
680
- def foreign_key_exists?(*args)
681
- @base.foreign_key_exists?(name, *args)
783
+ def foreign_key_exists?(*args, **options)
784
+ @base.foreign_key_exists?(name, *args, **options)
785
+ end
786
+
787
+ # Adds a check constraint.
788
+ #
789
+ # t.check_constraint("price > 0", name: "price_check")
790
+ #
791
+ # See {connection.add_check_constraint}[rdoc-ref:SchemaStatements#add_check_constraint]
792
+ def check_constraint(*args)
793
+ @base.add_check_constraint(name, *args)
794
+ end
795
+
796
+ # Removes the given check constraint from the table.
797
+ #
798
+ # t.remove_check_constraint(name: "price_check")
799
+ #
800
+ # See {connection.remove_check_constraint}[rdoc-ref:SchemaStatements#remove_check_constraint]
801
+ def remove_check_constraint(*args)
802
+ @base.remove_check_constraint(name, *args)
682
803
  end
683
804
  end
684
805
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/hash/compact"
4
-
5
3
  module ActiveRecord
6
4
  module ConnectionAdapters # :nodoc:
7
5
  class SchemaDumper < SchemaDumper # :nodoc:
@@ -15,8 +13,8 @@ module ActiveRecord
15
13
  end
16
14
 
17
15
  def column_spec_for_primary_key(column)
18
- return {} if default_primary_key?(column)
19
- spec = { id: schema_type(column).inspect }
16
+ spec = {}
17
+ spec[:id] = schema_type(column).inspect unless default_primary_key?(column)
20
18
  spec.merge!(prepare_column_options(column).except!(:null))
21
19
  spec[:default] ||= "nil" if explicit_primary_key_default?(column)
22
20
  spec