activerecord 5.0.6 → 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 (358) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +638 -2023
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +8 -6
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record/aggregations.rb +249 -246
  8. data/lib/active_record/association_relation.rb +24 -13
  9. data/lib/active_record/associations/alias_tracker.rb +24 -33
  10. data/lib/active_record/associations/association.rb +119 -56
  11. data/lib/active_record/associations/association_scope.rb +94 -94
  12. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  14. data/lib/active_record/associations/builder/association.rb +18 -25
  15. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  16. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -61
  18. data/lib/active_record/associations/builder/has_many.rb +4 -0
  19. data/lib/active_record/associations/builder/has_one.rb +37 -1
  20. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  21. data/lib/active_record/associations/collection_association.rb +80 -252
  22. data/lib/active_record/associations/collection_proxy.rb +158 -121
  23. data/lib/active_record/associations/foreign_association.rb +9 -0
  24. data/lib/active_record/associations/has_many_association.rb +23 -29
  25. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  26. data/lib/active_record/associations/has_one_association.rb +59 -54
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +38 -90
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  31. data/lib/active_record/associations/join_dependency.rb +134 -176
  32. data/lib/active_record/associations/preloader/association.rb +84 -125
  33. data/lib/active_record/associations/preloader/through_association.rb +82 -75
  34. data/lib/active_record/associations/preloader.rb +90 -102
  35. data/lib/active_record/associations/singular_association.rb +12 -45
  36. data/lib/active_record/associations/through_association.rb +26 -14
  37. data/lib/active_record/associations.rb +1603 -1592
  38. data/lib/active_record/attribute_assignment.rb +54 -60
  39. data/lib/active_record/attribute_decorators.rb +38 -15
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -7
  41. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  42. data/lib/active_record/attribute_methods/primary_key.rb +86 -91
  43. data/lib/active_record/attribute_methods/query.rb +4 -3
  44. data/lib/active_record/attribute_methods/read.rb +21 -49
  45. data/lib/active_record/attribute_methods/serialization.rb +30 -7
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -64
  47. data/lib/active_record/attribute_methods/write.rb +35 -33
  48. data/lib/active_record/attribute_methods.rb +66 -106
  49. data/lib/active_record/attributes.rb +38 -24
  50. data/lib/active_record/autosave_association.rb +53 -32
  51. data/lib/active_record/base.rb +27 -24
  52. data/lib/active_record/callbacks.rb +63 -33
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +11 -11
  55. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +553 -321
  56. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  57. data/lib/active_record/connection_adapters/abstract/database_statements.rb +213 -94
  58. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -28
  59. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
  60. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -27
  62. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -126
  63. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  64. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +369 -199
  65. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
  66. data/lib/active_record/connection_adapters/abstract_adapter.rb +363 -202
  67. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -551
  68. data/lib/active_record/connection_adapters/column.rb +41 -13
  69. data/lib/active_record/connection_adapters/connection_specification.rb +172 -138
  70. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  71. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +143 -49
  73. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -22
  74. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  75. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +50 -45
  76. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  77. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  78. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  79. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  80. data/lib/active_record/connection_adapters/mysql2_adapter.rb +49 -30
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +22 -7
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +60 -54
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -10
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -17
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  98. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +31 -9
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -30
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -4
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +35 -32
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +380 -300
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +10 -6
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +382 -275
  116. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +74 -19
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +254 -262
  126. data/lib/active_record/connection_adapters/statement_pool.rb +9 -7
  127. data/lib/active_record/connection_handling.rb +159 -40
  128. data/lib/active_record/core.rb +202 -162
  129. data/lib/active_record/counter_cache.rb +57 -28
  130. data/lib/active_record/database_configurations/database_config.rb +37 -0
  131. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  132. data/lib/active_record/database_configurations/url_config.rb +79 -0
  133. data/lib/active_record/database_configurations.rb +233 -0
  134. data/lib/active_record/define_callbacks.rb +22 -0
  135. data/lib/active_record/dynamic_matchers.rb +87 -86
  136. data/lib/active_record/enum.rb +60 -23
  137. data/lib/active_record/errors.rb +114 -18
  138. data/lib/active_record/explain.rb +4 -3
  139. data/lib/active_record/explain_registry.rb +3 -1
  140. data/lib/active_record/explain_subscriber.rb +9 -4
  141. data/lib/active_record/fixture_set/file.rb +13 -8
  142. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  143. data/lib/active_record/fixture_set/render_context.rb +17 -0
  144. data/lib/active_record/fixture_set/table_row.rb +153 -0
  145. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  146. data/lib/active_record/fixtures.rb +195 -502
  147. data/lib/active_record/gem_version.rb +4 -2
  148. data/lib/active_record/inheritance.rb +151 -97
  149. data/lib/active_record/insert_all.rb +179 -0
  150. data/lib/active_record/integration.rb +116 -25
  151. data/lib/active_record/internal_metadata.rb +15 -18
  152. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  153. data/lib/active_record/locking/optimistic.rb +78 -87
  154. data/lib/active_record/locking/pessimistic.rb +18 -6
  155. data/lib/active_record/log_subscriber.rb +48 -29
  156. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  157. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/migration/command_recorder.rb +143 -97
  160. data/lib/active_record/migration/compatibility.rb +174 -56
  161. data/lib/active_record/migration/join_table.rb +8 -6
  162. data/lib/active_record/migration.rb +367 -300
  163. data/lib/active_record/model_schema.rb +145 -139
  164. data/lib/active_record/nested_attributes.rb +214 -201
  165. data/lib/active_record/no_touching.rb +10 -1
  166. data/lib/active_record/null_relation.rb +13 -34
  167. data/lib/active_record/persistence.rb +442 -72
  168. data/lib/active_record/query_cache.rb +15 -14
  169. data/lib/active_record/querying.rb +36 -23
  170. data/lib/active_record/railtie.rb +128 -36
  171. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  172. data/lib/active_record/railties/console_sandbox.rb +2 -0
  173. data/lib/active_record/railties/controller_runtime.rb +34 -33
  174. data/lib/active_record/railties/databases.rake +309 -177
  175. data/lib/active_record/readonly_attributes.rb +5 -4
  176. data/lib/active_record/reflection.rb +211 -249
  177. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  178. data/lib/active_record/relation/batches.rb +99 -52
  179. data/lib/active_record/relation/calculations.rb +211 -172
  180. data/lib/active_record/relation/delegation.rb +67 -65
  181. data/lib/active_record/relation/finder_methods.rb +208 -247
  182. data/lib/active_record/relation/from_clause.rb +2 -8
  183. data/lib/active_record/relation/merger.rb +78 -61
  184. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  185. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  186. data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
  187. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  188. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  189. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  190. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  191. data/lib/active_record/relation/predicate_builder.rb +86 -104
  192. data/lib/active_record/relation/query_attribute.rb +33 -2
  193. data/lib/active_record/relation/query_methods.rb +458 -329
  194. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  195. data/lib/active_record/relation/spawn_methods.rb +8 -7
  196. data/lib/active_record/relation/where_clause.rb +111 -95
  197. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  198. data/lib/active_record/relation.rb +429 -318
  199. data/lib/active_record/result.rb +69 -39
  200. data/lib/active_record/runtime_registry.rb +5 -3
  201. data/lib/active_record/sanitization.rb +83 -99
  202. data/lib/active_record/schema.rb +7 -14
  203. data/lib/active_record/schema_dumper.rb +71 -69
  204. data/lib/active_record/schema_migration.rb +15 -5
  205. data/lib/active_record/scoping/default.rb +93 -95
  206. data/lib/active_record/scoping/named.rb +45 -25
  207. data/lib/active_record/scoping.rb +20 -19
  208. data/lib/active_record/secure_token.rb +4 -2
  209. data/lib/active_record/serialization.rb +2 -0
  210. data/lib/active_record/statement_cache.rb +63 -28
  211. data/lib/active_record/store.rb +121 -41
  212. data/lib/active_record/suppressor.rb +4 -1
  213. data/lib/active_record/table_metadata.rb +26 -20
  214. data/lib/active_record/tasks/database_tasks.rb +276 -85
  215. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -90
  216. data/lib/active_record/tasks/postgresql_database_tasks.rb +78 -47
  217. data/lib/active_record/tasks/sqlite_database_tasks.rb +34 -16
  218. data/lib/active_record/test_databases.rb +23 -0
  219. data/lib/active_record/test_fixtures.rb +224 -0
  220. data/lib/active_record/timestamp.rb +70 -35
  221. data/lib/active_record/touch_later.rb +7 -4
  222. data/lib/active_record/transactions.rb +133 -149
  223. data/lib/active_record/translation.rb +3 -1
  224. data/lib/active_record/type/adapter_specific_registry.rb +44 -45
  225. data/lib/active_record/type/date.rb +2 -0
  226. data/lib/active_record/type/date_time.rb +2 -0
  227. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  228. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  229. data/lib/active_record/type/internal/timezone.rb +2 -0
  230. data/lib/active_record/type/json.rb +30 -0
  231. data/lib/active_record/type/serialized.rb +16 -8
  232. data/lib/active_record/type/text.rb +11 -0
  233. data/lib/active_record/type/time.rb +2 -1
  234. data/lib/active_record/type/type_map.rb +13 -15
  235. data/lib/active_record/type/unsigned_integer.rb +17 -0
  236. data/lib/active_record/type.rb +23 -17
  237. data/lib/active_record/type_caster/connection.rb +17 -12
  238. data/lib/active_record/type_caster/map.rb +5 -4
  239. data/lib/active_record/type_caster.rb +4 -2
  240. data/lib/active_record/validations/absence.rb +2 -0
  241. data/lib/active_record/validations/associated.rb +3 -1
  242. data/lib/active_record/validations/length.rb +2 -0
  243. data/lib/active_record/validations/presence.rb +4 -2
  244. data/lib/active_record/validations/uniqueness.rb +29 -42
  245. data/lib/active_record/validations.rb +7 -4
  246. data/lib/active_record/version.rb +3 -1
  247. data/lib/active_record.rb +36 -22
  248. data/lib/arel/alias_predication.rb +9 -0
  249. data/lib/arel/attributes/attribute.rb +37 -0
  250. data/lib/arel/attributes.rb +22 -0
  251. data/lib/arel/collectors/bind.rb +24 -0
  252. data/lib/arel/collectors/composite.rb +31 -0
  253. data/lib/arel/collectors/plain_string.rb +20 -0
  254. data/lib/arel/collectors/sql_string.rb +20 -0
  255. data/lib/arel/collectors/substitute_binds.rb +28 -0
  256. data/lib/arel/crud.rb +42 -0
  257. data/lib/arel/delete_manager.rb +18 -0
  258. data/lib/arel/errors.rb +9 -0
  259. data/lib/arel/expressions.rb +29 -0
  260. data/lib/arel/factory_methods.rb +49 -0
  261. data/lib/arel/insert_manager.rb +49 -0
  262. data/lib/arel/math.rb +45 -0
  263. data/lib/arel/nodes/and.rb +32 -0
  264. data/lib/arel/nodes/ascending.rb +23 -0
  265. data/lib/arel/nodes/binary.rb +52 -0
  266. data/lib/arel/nodes/bind_param.rb +36 -0
  267. data/lib/arel/nodes/case.rb +55 -0
  268. data/lib/arel/nodes/casted.rb +50 -0
  269. data/lib/arel/nodes/comment.rb +29 -0
  270. data/lib/arel/nodes/count.rb +12 -0
  271. data/lib/arel/nodes/delete_statement.rb +45 -0
  272. data/lib/arel/nodes/descending.rb +23 -0
  273. data/lib/arel/nodes/equality.rb +18 -0
  274. data/lib/arel/nodes/extract.rb +24 -0
  275. data/lib/arel/nodes/false.rb +16 -0
  276. data/lib/arel/nodes/full_outer_join.rb +8 -0
  277. data/lib/arel/nodes/function.rb +44 -0
  278. data/lib/arel/nodes/grouping.rb +8 -0
  279. data/lib/arel/nodes/in.rb +8 -0
  280. data/lib/arel/nodes/infix_operation.rb +80 -0
  281. data/lib/arel/nodes/inner_join.rb +8 -0
  282. data/lib/arel/nodes/insert_statement.rb +37 -0
  283. data/lib/arel/nodes/join_source.rb +20 -0
  284. data/lib/arel/nodes/matches.rb +18 -0
  285. data/lib/arel/nodes/named_function.rb +23 -0
  286. data/lib/arel/nodes/node.rb +50 -0
  287. data/lib/arel/nodes/node_expression.rb +13 -0
  288. data/lib/arel/nodes/outer_join.rb +8 -0
  289. data/lib/arel/nodes/over.rb +15 -0
  290. data/lib/arel/nodes/regexp.rb +16 -0
  291. data/lib/arel/nodes/right_outer_join.rb +8 -0
  292. data/lib/arel/nodes/select_core.rb +67 -0
  293. data/lib/arel/nodes/select_statement.rb +41 -0
  294. data/lib/arel/nodes/sql_literal.rb +16 -0
  295. data/lib/arel/nodes/string_join.rb +11 -0
  296. data/lib/arel/nodes/table_alias.rb +27 -0
  297. data/lib/arel/nodes/terminal.rb +16 -0
  298. data/lib/arel/nodes/true.rb +16 -0
  299. data/lib/arel/nodes/unary.rb +45 -0
  300. data/lib/arel/nodes/unary_operation.rb +20 -0
  301. data/lib/arel/nodes/unqualified_column.rb +22 -0
  302. data/lib/arel/nodes/update_statement.rb +41 -0
  303. data/lib/arel/nodes/values_list.rb +9 -0
  304. data/lib/arel/nodes/window.rb +126 -0
  305. data/lib/arel/nodes/with.rb +11 -0
  306. data/lib/arel/nodes.rb +68 -0
  307. data/lib/arel/order_predications.rb +13 -0
  308. data/lib/arel/predications.rb +257 -0
  309. data/lib/arel/select_manager.rb +271 -0
  310. data/lib/arel/table.rb +110 -0
  311. data/lib/arel/tree_manager.rb +72 -0
  312. data/lib/arel/update_manager.rb +34 -0
  313. data/lib/arel/visitors/depth_first.rb +204 -0
  314. data/lib/arel/visitors/dot.rb +297 -0
  315. data/lib/arel/visitors/ibm_db.rb +34 -0
  316. data/lib/arel/visitors/informix.rb +62 -0
  317. data/lib/arel/visitors/mssql.rb +157 -0
  318. data/lib/arel/visitors/mysql.rb +83 -0
  319. data/lib/arel/visitors/oracle.rb +159 -0
  320. data/lib/arel/visitors/oracle12.rb +66 -0
  321. data/lib/arel/visitors/postgresql.rb +110 -0
  322. data/lib/arel/visitors/sqlite.rb +39 -0
  323. data/lib/arel/visitors/to_sql.rb +889 -0
  324. data/lib/arel/visitors/visitor.rb +46 -0
  325. data/lib/arel/visitors/where_sql.rb +23 -0
  326. data/lib/arel/visitors.rb +20 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +58 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  330. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  332. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  334. data/lib/rails/generators/active_record/migration.rb +17 -2
  335. data/lib/rails/generators/active_record/model/model_generator.rb +9 -29
  336. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  337. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +133 -50
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  347. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  348. data/lib/active_record/attribute.rb +0 -213
  349. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  350. data/lib/active_record/attribute_set/builder.rb +0 -130
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/collection_cache_key.rb +0 -50
  353. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  354. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  355. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  356. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  357. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  358. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,6 +1,9 @@
1
- require 'active_record/migration/join_table'
2
- require 'active_support/core_ext/string/access'
3
- require 'digest'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/migration/join_table"
4
+ require "active_support/core_ext/string/access"
5
+ require "active_support/deprecation"
6
+ require "digest/sha2"
4
7
 
5
8
  module ActiveRecord
6
9
  module ConnectionAdapters # :nodoc:
@@ -25,12 +28,14 @@ module ActiveRecord
25
28
 
26
29
  # Truncates a table alias according to the limits of the current adapter.
27
30
  def table_alias_for(table_name)
28
- table_name[0...table_alias_length].tr('.', '_')
31
+ table_name[0...table_alias_length].tr(".", "_")
29
32
  end
30
33
 
31
34
  # Returns the relation names useable to back Active Record models.
32
35
  # For most adapters this means all #tables and #views.
33
36
  def data_sources
37
+ query_values(data_source_sql, "SCHEMA")
38
+ rescue NotImplementedError
34
39
  tables | views
35
40
  end
36
41
 
@@ -39,12 +44,14 @@ module ActiveRecord
39
44
  # data_source_exists?(:ebooks)
40
45
  #
41
46
  def data_source_exists?(name)
47
+ query_values(data_source_sql(name), "SCHEMA").any? if name.present?
48
+ rescue NotImplementedError
42
49
  data_sources.include?(name.to_s)
43
50
  end
44
51
 
45
52
  # Returns an array of table names defined in the database.
46
- def tables(name = nil)
47
- raise NotImplementedError, "#tables is not implemented"
53
+ def tables
54
+ query_values(data_source_sql(type: "BASE TABLE"), "SCHEMA")
48
55
  end
49
56
 
50
57
  # Checks to see if the table +table_name+ exists on the database.
@@ -52,12 +59,14 @@ module ActiveRecord
52
59
  # table_exists?(:developers)
53
60
  #
54
61
  def table_exists?(table_name)
62
+ query_values(data_source_sql(table_name, type: "BASE TABLE"), "SCHEMA").any? if table_name.present?
63
+ rescue NotImplementedError
55
64
  tables.include?(table_name.to_s)
56
65
  end
57
66
 
58
67
  # Returns an array of view names defined in the database.
59
68
  def views
60
- raise NotImplementedError, "#views is not implemented"
69
+ query_values(data_source_sql(type: "VIEW"), "SCHEMA")
61
70
  end
62
71
 
63
72
  # Checks to see if the view +view_name+ exists on the database.
@@ -65,11 +74,15 @@ module ActiveRecord
65
74
  # view_exists?(:ebooks)
66
75
  #
67
76
  def view_exists?(view_name)
77
+ query_values(data_source_sql(view_name, type: "VIEW"), "SCHEMA").any? if view_name.present?
78
+ rescue NotImplementedError
68
79
  views.include?(view_name.to_s)
69
80
  end
70
81
 
71
82
  # Returns an array of indexes for the given table.
72
- # def indexes(table_name, name = nil) end
83
+ def indexes(table_name)
84
+ raise NotImplementedError, "#indexes is not implemented"
85
+ end
73
86
 
74
87
  # Checks to see if an index exists on a table for a given index definition.
75
88
  #
@@ -88,17 +101,19 @@ module ActiveRecord
88
101
  def index_exists?(table_name, column_name, options = {})
89
102
  column_names = Array(column_name).map(&:to_s)
90
103
  checks = []
91
- checks << lambda { |i| i.columns == column_names }
104
+ checks << lambda { |i| Array(i.columns) == column_names }
92
105
  checks << lambda { |i| i.unique } if options[:unique]
93
106
  checks << lambda { |i| i.name == options[:name].to_s } if options[:name]
94
107
 
95
108
  indexes(table_name).any? { |i| checks.all? { |check| check[i] } }
96
109
  end
97
110
 
98
- # Returns an array of Column objects for the table specified by +table_name+.
99
- # See the concrete implementation for details on the expected parameter values.
111
+ # Returns an array of +Column+ objects for the table specified by +table_name+.
100
112
  def columns(table_name)
101
- raise NotImplementedError, "#columns is not implemented"
113
+ table_name = table_name.to_s
114
+ column_definitions(table_name).map do |field|
115
+ new_column_from_field(table_name, field)
116
+ end
102
117
  end
103
118
 
104
119
  # Checks to see if a column exists in a given table.
@@ -115,12 +130,12 @@ module ActiveRecord
115
130
  # column_exists?(:suppliers, :name, :string, null: false)
116
131
  # column_exists?(:suppliers, :tax, :decimal, precision: 8, scale: 2)
117
132
  #
118
- def column_exists?(table_name, column_name, type = nil, options = {})
133
+ def column_exists?(table_name, column_name, type = nil, **options)
119
134
  column_name = column_name.to_s
120
135
  checks = []
121
136
  checks << lambda { |c| c.name == column_name }
122
- checks << lambda { |c| c.type == type } if type
123
- (migration_keys - [:name]).each do |attr|
137
+ checks << lambda { |c| c.type == type.to_sym rescue nil } if type
138
+ column_options_keys.each do |attr|
124
139
  checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
125
140
  end
126
141
 
@@ -174,7 +189,9 @@ module ActiveRecord
174
189
  # A Symbol can be used to specify the type of the generated primary key column.
175
190
  # [<tt>:primary_key</tt>]
176
191
  # The name of the primary key, if one is to be added automatically.
177
- # Defaults to +id+. If <tt>:id</tt> is false this option is ignored.
192
+ # Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored.
193
+ #
194
+ # If an array is passed, a composite primary key will be created.
178
195
  #
179
196
  # Note that Active Record models will automatically detect their
180
197
  # primary key. This can be avoided by using
@@ -189,19 +206,22 @@ module ActiveRecord
189
206
  # Set to true to drop the table before creating it.
190
207
  # Set to +:cascade+ to drop dependent objects as well.
191
208
  # Defaults to false.
209
+ # [<tt>:if_not_exists</tt>]
210
+ # Set to true to avoid raising an error when the table already exists.
211
+ # Defaults to false.
192
212
  # [<tt>:as</tt>]
193
213
  # SQL to use to generate the table. When this option is used, the block is
194
214
  # ignored, as are the <tt>:id</tt> and <tt>:primary_key</tt> options.
195
215
  #
196
216
  # ====== Add a backend specific option to the generated SQL (MySQL)
197
217
  #
198
- # create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
218
+ # create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4')
199
219
  #
200
220
  # generates:
201
221
  #
202
222
  # CREATE TABLE suppliers (
203
- # id int auto_increment PRIMARY KEY
204
- # ) ENGINE=InnoDB DEFAULT CHARSET=utf8
223
+ # id bigint auto_increment PRIMARY KEY
224
+ # ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
205
225
  #
206
226
  # ====== Rename the primary key column
207
227
  #
@@ -212,7 +232,7 @@ module ActiveRecord
212
232
  # generates:
213
233
  #
214
234
  # CREATE TABLE objects (
215
- # guid int auto_increment PRIMARY KEY,
235
+ # guid bigint auto_increment PRIMARY KEY,
216
236
  # name varchar(80)
217
237
  # )
218
238
  #
@@ -229,18 +249,35 @@ module ActiveRecord
229
249
  # label varchar
230
250
  # )
231
251
  #
252
+ # ====== Create a composite primary key
253
+ #
254
+ # create_table(:orders, primary_key: [:product_id, :client_id]) do |t|
255
+ # t.belongs_to :product
256
+ # t.belongs_to :client
257
+ # end
258
+ #
259
+ # generates:
260
+ #
261
+ # CREATE TABLE order (
262
+ # product_id bigint NOT NULL,
263
+ # client_id bigint NOT NULL
264
+ # );
265
+ #
266
+ # ALTER TABLE ONLY "orders"
267
+ # ADD CONSTRAINT orders_pkey PRIMARY KEY (product_id, client_id);
268
+ #
232
269
  # ====== Do not add a primary key column
233
270
  #
234
271
  # create_table(:categories_suppliers, id: false) do |t|
235
- # t.column :category_id, :integer
236
- # t.column :supplier_id, :integer
272
+ # t.column :category_id, :bigint
273
+ # t.column :supplier_id, :bigint
237
274
  # end
238
275
  #
239
276
  # generates:
240
277
  #
241
278
  # CREATE TABLE categories_suppliers (
242
- # category_id int,
243
- # supplier_id int
279
+ # category_id bigint,
280
+ # supplier_id bigint
244
281
  # )
245
282
  #
246
283
  # ====== Create a temporary table based on a query
@@ -254,8 +291,8 @@ module ActiveRecord
254
291
  # SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
255
292
  #
256
293
  # See also TableDefinition#column for details on how to create columns.
257
- def create_table(table_name, comment: nil, **options)
258
- td = create_table_definition table_name, options[:temporary], options[:options], options[:as], comment: comment
294
+ def create_table(table_name, **options)
295
+ td = create_table_definition(table_name, options)
259
296
 
260
297
  if options[:id] != false && !options[:as]
261
298
  pk = options.fetch(:primary_key) do
@@ -265,14 +302,14 @@ module ActiveRecord
265
302
  if pk.is_a?(Array)
266
303
  td.primary_keys pk
267
304
  else
268
- td.primary_key pk, options.fetch(:id, :primary_key), options
305
+ td.primary_key pk, options.fetch(:id, :primary_key), options.except(:comment)
269
306
  end
270
307
  end
271
308
 
272
309
  yield td if block_given?
273
310
 
274
- if options[:force] && data_source_exists?(table_name)
275
- drop_table(table_name, options)
311
+ if options[:force]
312
+ drop_table(table_name, options.merge(if_exists: true))
276
313
  end
277
314
 
278
315
  result = execute schema_creation.accept td
@@ -284,7 +321,9 @@ module ActiveRecord
284
321
  end
285
322
 
286
323
  if supports_comments? && !supports_comments_in_create?
287
- change_table_comment(table_name, comment) if comment.present?
324
+ if table_comment = options[:comment].presence
325
+ change_table_comment(table_name, table_comment)
326
+ end
288
327
 
289
328
  td.columns.each do |column|
290
329
  change_column_comment(table_name, column.name, column.comment) if column.comment.present?
@@ -300,9 +339,9 @@ module ActiveRecord
300
339
  # # Creates a table called 'assemblies_parts' with no id.
301
340
  # create_join_table(:assemblies, :parts)
302
341
  #
303
- # You can pass a +options+ hash can include the following keys:
342
+ # You can pass an +options+ hash which can include the following keys:
304
343
  # [<tt>:table_name</tt>]
305
- # Sets the table name overriding the default
344
+ # Sets the table name, overriding the default.
306
345
  # [<tt>:column_options</tt>]
307
346
  # Any extra options you want appended to the columns definition.
308
347
  # [<tt>:options</tt>]
@@ -328,22 +367,20 @@ module ActiveRecord
328
367
  # generates:
329
368
  #
330
369
  # CREATE TABLE assemblies_parts (
331
- # assembly_id int NOT NULL,
332
- # part_id int NOT NULL,
370
+ # assembly_id bigint NOT NULL,
371
+ # part_id bigint NOT NULL,
333
372
  # ) ENGINE=InnoDB DEFAULT CHARSET=utf8
334
373
  #
335
- def create_join_table(table_1, table_2, options = {})
374
+ def create_join_table(table_1, table_2, column_options: {}, **options)
336
375
  join_table_name = find_join_table_name(table_1, table_2, options)
337
376
 
338
- column_options = options.delete(:column_options) || {}
339
- column_options.reverse_merge!(null: false)
340
- type = column_options.delete(:type) || :integer
377
+ column_options.reverse_merge!(null: false, index: false)
341
378
 
342
- t1_column, t2_column = [table_1, table_2].map{ |t| t.to_s.singularize.foreign_key }
379
+ t1_ref, t2_ref = [table_1, table_2].map { |t| t.to_s.singularize }
343
380
 
344
381
  create_table(join_table_name, options.merge!(id: false)) do |td|
345
- td.send type, t1_column, column_options
346
- td.send type, t2_column, column_options
382
+ td.references t1_ref, column_options
383
+ td.references t2_ref, column_options
347
384
  yield td if block_given?
348
385
  end
349
386
  end
@@ -375,6 +412,8 @@ module ActiveRecord
375
412
  #
376
413
  # Defaults to false.
377
414
  #
415
+ # Only supported on the MySQL and PostgreSQL adapter, ignored elsewhere.
416
+ #
378
417
  # ====== Add a column
379
418
  #
380
419
  # change_table(:suppliers) do |t|
@@ -399,7 +438,7 @@ module ActiveRecord
399
438
  # t.references :company
400
439
  # end
401
440
  #
402
- # Creates a <tt>company_id(integer)</tt> column.
441
+ # Creates a <tt>company_id(bigint)</tt> column.
403
442
  #
404
443
  # ====== Add a polymorphic foreign key column
405
444
  #
@@ -407,7 +446,7 @@ module ActiveRecord
407
446
  # t.belongs_to :company, polymorphic: true
408
447
  # end
409
448
  #
410
- # Creates <tt>company_type(varchar)</tt> and <tt>company_id(integer)</tt> columns.
449
+ # Creates <tt>company_type(varchar)</tt> and <tt>company_id(bigint)</tt> columns.
411
450
  #
412
451
  # ====== Remove a column
413
452
  #
@@ -428,7 +467,7 @@ module ActiveRecord
428
467
  # t.remove_index :company_id
429
468
  # end
430
469
  #
431
- # See also Table for details on all of the various column transformation.
470
+ # See also Table for details on all of the various column transformations.
432
471
  def change_table(table_name, options = {})
433
472
  if supports_bulk_alter? && options[:bulk]
434
473
  recorder = ActiveRecord::Migration::CommandRecorder.new(self)
@@ -478,19 +517,25 @@ module ActiveRecord
478
517
  #
479
518
  # Available options are (none of these exists by default):
480
519
  # * <tt>:limit</tt> -
481
- # Requests a maximum column length. This is number of characters for a <tt>:string</tt> column
482
- # and number of bytes for <tt>:text</tt>, <tt>:binary</tt> and <tt>:integer</tt> columns.
520
+ # Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
521
+ # and number of bytes for <tt>:text</tt>, <tt>:binary</tt>, and <tt>:integer</tt> columns.
522
+ # This option is ignored by some backends.
483
523
  # * <tt>:default</tt> -
484
- # The column's default value. Use nil for NULL.
524
+ # The column's default value. Use +nil+ for +NULL+.
485
525
  # * <tt>:null</tt> -
486
- # Allows or disallows +NULL+ values in the column. This option could
487
- # have been named <tt>:null_allowed</tt>.
526
+ # Allows or disallows +NULL+ values in the column.
488
527
  # * <tt>:precision</tt> -
489
- # Specifies the precision for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
528
+ # Specifies the precision for the <tt>:decimal</tt>, <tt>:numeric</tt>,
529
+ # <tt>:datetime</tt>, and <tt>:time</tt> columns.
490
530
  # * <tt>:scale</tt> -
491
531
  # Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
532
+ # * <tt>:collation</tt> -
533
+ # Specifies the collation for a <tt>:string</tt> or <tt>:text</tt> column. If not specified, the
534
+ # column will have the same collation as the table.
535
+ # * <tt>:comment</tt> -
536
+ # Specifies the comment for the column. This option is ignored by some backends.
492
537
  #
493
- # Note: The precision is the total number of significant digits
538
+ # Note: The precision is the total number of significant digits,
494
539
  # and the scale is the number of digits that can be stored following
495
540
  # the decimal point. For example, the number 123.45 has a precision of 5
496
541
  # and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
@@ -511,7 +556,7 @@ module ActiveRecord
511
556
  # Default is (38,0).
512
557
  # * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
513
558
  # Default unknown.
514
- # * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
559
+ # * SqlServer: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
515
560
  # Default (38,0).
516
561
  #
517
562
  # == Examples
@@ -533,10 +578,14 @@ module ActiveRecord
533
578
  # add_column(:measurements, :huge_integer, :decimal, precision: 30)
534
579
  # # ALTER TABLE "measurements" ADD "huge_integer" decimal(30)
535
580
  #
581
+ # # Defines a column that stores an array of a type.
582
+ # add_column(:users, :skills, :text, array: true)
583
+ # # ALTER TABLE "users" ADD "skills" text[]
584
+ #
536
585
  # # Defines a column with a database-specific type.
537
586
  # add_column(:shapes, :triangle, 'polygon')
538
587
  # # ALTER TABLE "shapes" ADD "triangle" polygon
539
- def add_column(table_name, column_name, type, options = {})
588
+ def add_column(table_name, column_name, type, **options)
540
589
  at = create_alter_table table_name
541
590
  at.add_column(column_name, type, options)
542
591
  execute schema_creation.accept at
@@ -559,9 +608,10 @@ module ActiveRecord
559
608
  #
560
609
  # The +type+ and +options+ parameters will be ignored if present. It can be helpful
561
610
  # to provide these in a migration's +change+ method so it can be reverted.
562
- # In that case, +type+ and +options+ will be used by add_column.
611
+ # In that case, +type+ and +options+ will be used by #add_column.
612
+ # Indexes on the column are automatically removed.
563
613
  def remove_column(table_name, column_name, type = nil, options = {})
564
- execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}"
614
+ execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, options)}"
565
615
  end
566
616
 
567
617
  # Changes the column's definition according to the new options.
@@ -676,7 +726,7 @@ module ActiveRecord
676
726
  #
677
727
  # CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
678
728
  #
679
- # Note: MySQL doesn't yet support index order (it accepts the syntax but ignores it).
729
+ # Note: MySQL only supports index order from 8.0.1 onwards (earlier versions accepted the syntax but ignored it).
680
730
  #
681
731
  # ====== Creating a partial index
682
732
  #
@@ -699,6 +749,19 @@ module ActiveRecord
699
749
  #
700
750
  # Note: only supported by PostgreSQL and MySQL
701
751
  #
752
+ # ====== Creating an index with a specific operator class
753
+ #
754
+ # add_index(:developers, :name, using: 'gist', opclass: :gist_trgm_ops)
755
+ # # CREATE INDEX developers_on_name ON developers USING gist (name gist_trgm_ops) -- PostgreSQL
756
+ #
757
+ # add_index(:developers, [:name, :city], using: 'gist', opclass: { city: :gist_trgm_ops })
758
+ # # CREATE INDEX developers_on_name_and_city ON developers USING gist (name, city gist_trgm_ops) -- PostgreSQL
759
+ #
760
+ # add_index(:developers, [:name, :city], using: 'gist', opclass: :gist_trgm_ops)
761
+ # # CREATE INDEX developers_on_name_and_city ON developers USING gist (name gist_trgm_ops, city gist_trgm_ops) -- PostgreSQL
762
+ #
763
+ # Note: only supported by PostgreSQL
764
+ #
702
765
  # ====== Creating an index with a specific type
703
766
  #
704
767
  # add_index(:developers, :name, type: :fulltext)
@@ -708,6 +771,17 @@ module ActiveRecord
708
771
  # CREATE FULLTEXT INDEX index_developers_on_name ON developers (name) -- MySQL
709
772
  #
710
773
  # Note: only supported by MySQL.
774
+ #
775
+ # ====== Creating an index with a specific algorithm
776
+ #
777
+ # add_index(:developers, :name, algorithm: :concurrently)
778
+ # # CREATE INDEX CONCURRENTLY developers_on_name on developers (name)
779
+ #
780
+ # Note: only supported by PostgreSQL.
781
+ #
782
+ # Concurrently adding an index is not supported in a transaction.
783
+ #
784
+ # For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
711
785
  def add_index(table_name, column_name, options = {})
712
786
  index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, options)
713
787
  execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})#{index_options}"
@@ -731,6 +805,15 @@ module ActiveRecord
731
805
  #
732
806
  # remove_index :accounts, name: :by_branch_party
733
807
  #
808
+ # Removes the index named +by_branch_party+ in the +accounts+ table +concurrently+.
809
+ #
810
+ # remove_index :accounts, name: :by_branch_party, algorithm: :concurrently
811
+ #
812
+ # Note: only supported by PostgreSQL.
813
+ #
814
+ # Concurrently removing an index is not supported in a transaction.
815
+ #
816
+ # For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
734
817
  def remove_index(table_name, options = {})
735
818
  index_name = index_name_for_remove(table_name, options)
736
819
  execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
@@ -745,7 +828,7 @@ module ActiveRecord
745
828
  def rename_index(table_name, old_name, new_name)
746
829
  validate_index_length!(table_name, new_name)
747
830
 
748
- # this is a naive implementation; some DBs may support this more efficiently (Postgres, for instance)
831
+ # this is a naive implementation; some DBs may support this more efficiently (PostgreSQL, for instance)
749
832
  old_index_def = indexes(table_name).detect { |i| i.name == old_name }
750
833
  return unless old_index_def
751
834
  add_index(table_name, old_index_def.columns, name: new_name, unique: old_index_def.unique)
@@ -767,23 +850,19 @@ module ActiveRecord
767
850
  end
768
851
 
769
852
  # Verifies the existence of an index with a given name.
770
- #
771
- # The default argument is returned if the underlying implementation does not define the indexes method,
772
- # as there's no way to determine the correct answer in that case.
773
- def index_name_exists?(table_name, index_name, default)
774
- return default unless respond_to?(:indexes)
853
+ def index_name_exists?(table_name, index_name)
775
854
  index_name = index_name.to_s
776
855
  indexes(table_name).detect { |i| i.name == index_name }
777
856
  end
778
857
 
779
- # Adds a reference. The reference column is an integer by default,
858
+ # Adds a reference. The reference column is a bigint by default,
780
859
  # the <tt>:type</tt> option can be used to specify a different type.
781
860
  # Optionally adds a +_type+ column, if <tt>:polymorphic</tt> option is provided.
782
861
  # #add_reference and #add_belongs_to are acceptable.
783
862
  #
784
863
  # The +options+ hash can include the following keys:
785
864
  # [<tt>:type</tt>]
786
- # The reference column type. Defaults to +:integer+.
865
+ # The reference column type. Defaults to +:bigint+.
787
866
  # [<tt>:index</tt>]
788
867
  # Add an appropriate index. Defaults to true.
789
868
  # See #add_index for usage of this option.
@@ -794,17 +873,17 @@ module ActiveRecord
794
873
  # [<tt>:null</tt>]
795
874
  # Whether the column allows nulls. Defaults to true.
796
875
  #
797
- # ====== Create a user_id integer column
876
+ # ====== Create a user_id bigint column without an index
798
877
  #
799
- # add_reference(:products, :user)
878
+ # add_reference(:products, :user, index: false)
800
879
  #
801
880
  # ====== Create a user_id string column
802
881
  #
803
882
  # add_reference(:products, :user, type: :string)
804
883
  #
805
- # ====== Create supplier_id, supplier_type columns and appropriate index
884
+ # ====== Create supplier_id, supplier_type columns
806
885
  #
807
- # add_reference(:products, :supplier, polymorphic: true, index: true)
886
+ # add_reference(:products, :supplier, polymorphic: true)
808
887
  #
809
888
  # ====== Create a supplier_id column with a unique index
810
889
  #
@@ -822,8 +901,8 @@ module ActiveRecord
822
901
  #
823
902
  # add_reference(:products, :supplier, foreign_key: {to_table: :firms})
824
903
  #
825
- def add_reference(table_name, *args)
826
- ReferenceDefinition.new(*args).add_to(update_table_definition(table_name, self))
904
+ def add_reference(table_name, ref_name, **options)
905
+ ReferenceDefinition.new(ref_name, options).add_to(update_table_definition(table_name, self))
827
906
  end
828
907
  alias :add_belongs_to :add_reference
829
908
 
@@ -832,7 +911,7 @@ module ActiveRecord
832
911
  #
833
912
  # ====== Remove the reference
834
913
  #
835
- # remove_reference(:products, :user, index: true)
914
+ # remove_reference(:products, :user, index: false)
836
915
  #
837
916
  # ====== Remove polymorphic reference
838
917
  #
@@ -840,7 +919,7 @@ module ActiveRecord
840
919
  #
841
920
  # ====== Remove the reference with a foreign key
842
921
  #
843
- # remove_reference(:products, :user, index: true, foreign_key: true)
922
+ # remove_reference(:products, :user, foreign_key: true)
844
923
  #
845
924
  def remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options)
846
925
  if foreign_key
@@ -850,7 +929,8 @@ module ActiveRecord
850
929
  else
851
930
  foreign_key_options = { to_table: reference_name }
852
931
  end
853
- remove_foreign_key(table_name, **foreign_key_options)
932
+ foreign_key_options[:column] ||= "#{ref_name}_id"
933
+ remove_foreign_key(table_name, foreign_key_options)
854
934
  end
855
935
 
856
936
  remove_column(table_name, "#{ref_name}_id")
@@ -906,6 +986,8 @@ module ActiveRecord
906
986
  # Action that happens <tt>ON DELETE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
907
987
  # [<tt>:on_update</tt>]
908
988
  # Action that happens <tt>ON UPDATE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
989
+ # [<tt>:validate</tt>]
990
+ # (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+.
909
991
  def add_foreign_key(from_table, to_table, options = {})
910
992
  return unless supports_foreign_keys?
911
993
 
@@ -929,15 +1011,22 @@ module ActiveRecord
929
1011
  #
930
1012
  # remove_foreign_key :accounts, column: :owner_id
931
1013
  #
1014
+ # Removes the foreign key on +accounts.owner_id+.
1015
+ #
1016
+ # remove_foreign_key :accounts, to_table: :owners
1017
+ #
932
1018
  # Removes the foreign key named +special_fk_name+ on the +accounts+ table.
933
1019
  #
934
1020
  # remove_foreign_key :accounts, name: :special_fk_name
935
1021
  #
936
- # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key.
937
- def remove_foreign_key(from_table, options_or_to_table = {})
1022
+ # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key
1023
+ # with an addition of
1024
+ # [<tt>:to_table</tt>]
1025
+ # The name of the table that contains the referenced primary key.
1026
+ def remove_foreign_key(from_table, to_table = nil, **options)
938
1027
  return unless supports_foreign_keys?
939
1028
 
940
- fk_name_to_delete = foreign_key_for!(from_table, options_or_to_table).name
1029
+ fk_name_to_delete = foreign_key_for!(from_table, to_table: to_table, **options).name
941
1030
 
942
1031
  at = create_alter_table from_table
943
1032
  at.drop_foreign_key fk_name_to_delete
@@ -947,33 +1036,21 @@ module ActiveRecord
947
1036
 
948
1037
  # Checks to see if a foreign key exists on a table for a given foreign key definition.
949
1038
  #
950
- # # Check a foreign key exists
1039
+ # # Checks to see if a foreign key exists.
951
1040
  # foreign_key_exists?(:accounts, :branches)
952
1041
  #
953
- # # Check a foreign key on a specified column exists
1042
+ # # Checks to see if a foreign key on a specified column exists.
954
1043
  # foreign_key_exists?(:accounts, column: :owner_id)
955
1044
  #
956
- # # Check a foreign key with a custom name exists
1045
+ # # Checks to see if a foreign key with a custom name exists.
957
1046
  # foreign_key_exists?(:accounts, name: "special_fk_name")
958
1047
  #
959
- def foreign_key_exists?(from_table, options_or_to_table = {})
960
- foreign_key_for(from_table, options_or_to_table).present?
961
- end
962
-
963
- def foreign_key_for(from_table, options_or_to_table = {}) # :nodoc:
964
- return unless supports_foreign_keys?
965
- foreign_keys(from_table).detect {|fk| fk.defined_for? options_or_to_table }
966
- end
967
-
968
- def foreign_key_for!(from_table, options_or_to_table = {}) # :nodoc:
969
- foreign_key_for(from_table, options_or_to_table) or \
970
- raise ArgumentError, "Table '#{from_table}' has no foreign key for #{options_or_to_table}"
1048
+ def foreign_key_exists?(from_table, to_table = nil, **options)
1049
+ foreign_key_for(from_table, to_table: to_table, **options).present?
971
1050
  end
972
1051
 
973
1052
  def foreign_key_column_for(table_name) # :nodoc:
974
- prefix = Base.table_name_prefix
975
- suffix = Base.table_name_suffix
976
- name = table_name.to_s =~ /#{prefix}(.+)#{suffix}/ ? $1 : table_name.to_s
1053
+ name = strip_table_name_prefix_and_suffix(table_name)
977
1054
  "#{name.singularize}_id"
978
1055
  end
979
1056
 
@@ -984,68 +1061,42 @@ module ActiveRecord
984
1061
  options
985
1062
  end
986
1063
 
987
- def dump_schema_information #:nodoc:
988
- versions = ActiveRecord::SchemaMigration.order('version').pluck(:version)
1064
+ def dump_schema_information # :nodoc:
1065
+ versions = schema_migration.all_versions
989
1066
  insert_versions_sql(versions) if versions.any?
990
1067
  end
991
1068
 
992
- def insert_versions_sql(versions) # :nodoc:
993
- sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)
994
-
995
- if versions.is_a?(Array)
996
- sql = "INSERT INTO #{sm_table} (version) VALUES\n"
997
- sql << versions.map { |v| "(#{quote(v)})" }.join(",\n")
998
- sql << ";\n\n"
999
- sql
1000
- else
1001
- "INSERT INTO #{sm_table} (version) VALUES (#{quote(versions)});"
1002
- end
1003
- end
1004
-
1005
- # Should not be called normally, but this operation is non-destructive.
1006
- # The migrations module handles this automatically.
1007
- def initialize_schema_migrations_table
1008
- ActiveRecord::SchemaMigration.create_table
1009
- end
1010
-
1011
- def initialize_internal_metadata_table
1012
- ActiveRecord::InternalMetadata.create_table
1013
- end
1014
-
1015
1069
  def internal_string_options_for_primary_key # :nodoc:
1016
1070
  { primary_key: true }
1017
1071
  end
1018
1072
 
1019
- def assume_migrated_upto_version(version, migrations_paths)
1020
- migrations_paths = Array(migrations_paths)
1073
+ def assume_migrated_upto_version(version, migrations_paths = nil)
1074
+ unless migrations_paths.nil?
1075
+ ActiveSupport::Deprecation.warn(<<~MSG.squish)
1076
+ Passing migrations_paths to #assume_migrated_upto_version is deprecated and will be removed in Rails 6.1.
1077
+ MSG
1078
+ end
1079
+
1021
1080
  version = version.to_i
1022
- sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)
1081
+ sm_table = quote_table_name(schema_migration.table_name)
1023
1082
 
1024
- migrated = select_values("SELECT version FROM #{sm_table}").map(&:to_i)
1025
- versions = ActiveRecord::Migrator.migration_files(migrations_paths).map do |file|
1026
- ActiveRecord::Migrator.parse_migration_filename(file).first.to_i
1027
- end
1083
+ migrated = migration_context.get_all_versions
1084
+ versions = migration_context.migrations.map(&:version)
1028
1085
 
1029
1086
  unless migrated.include?(version)
1030
1087
  execute "INSERT INTO #{sm_table} (version) VALUES (#{quote(version)})"
1031
1088
  end
1032
1089
 
1033
- inserting = (versions - migrated).select {|v| v < version}
1090
+ inserting = (versions - migrated).select { |v| v < version }
1034
1091
  if inserting.any?
1035
- if (duplicate = inserting.detect {|v| inserting.count(v) > 1})
1092
+ if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
1036
1093
  raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
1037
1094
  end
1038
- if supports_multi_insert?
1039
- execute insert_versions_sql(inserting)
1040
- else
1041
- inserting.each do |v|
1042
- execute insert_versions_sql(v)
1043
- end
1044
- end
1095
+ execute insert_versions_sql(inserting)
1045
1096
  end
1046
1097
  end
1047
1098
 
1048
- def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
1099
+ def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) # :nodoc:
1049
1100
  type = type.to_sym if type
1050
1101
  if native = native_database_types[type]
1051
1102
  column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
@@ -1063,11 +1114,11 @@ module ActiveRecord
1063
1114
  raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale is specified"
1064
1115
  end
1065
1116
 
1066
- elsif [:datetime, :time].include?(type) && precision ||= native[:precision]
1117
+ elsif [:datetime, :timestamp, :time, :interval].include?(type) && precision ||= native[:precision]
1067
1118
  if (0..6) === precision
1068
1119
  column_type_sql << "(#{precision})"
1069
1120
  else
1070
- raise(ActiveRecordError, "No #{native[:name]} type has precision of #{precision}. The allowed range of precision is from 0 to 6")
1121
+ raise ArgumentError, "No #{native[:name]} type has precision of #{precision}. The allowed range of precision is from 0 to 6"
1071
1122
  end
1072
1123
  elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit])
1073
1124
  column_type_sql << "(#{limit})"
@@ -1080,7 +1131,7 @@ module ActiveRecord
1080
1131
  end
1081
1132
 
1082
1133
  # Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT.
1083
- # PostgreSQL, MySQL, and Oracle overrides this for custom DISTINCT syntax - they
1134
+ # PostgreSQL, MySQL, and Oracle override this for custom DISTINCT syntax - they
1084
1135
  # require the order columns appear in the SELECT.
1085
1136
  #
1086
1137
  # columns_for_distinct("posts.id", ["posts.created_at desc"])
@@ -1097,6 +1148,10 @@ module ActiveRecord
1097
1148
  def add_timestamps(table_name, options = {})
1098
1149
  options[:null] = false if options[:null].nil?
1099
1150
 
1151
+ if !options.key?(:precision) && supports_datetime_with_precision?
1152
+ options[:precision] = 6
1153
+ end
1154
+
1100
1155
  add_column table_name, :created_at, :datetime, options
1101
1156
  add_column table_name, :updated_at, :datetime, options
1102
1157
  end
@@ -1117,13 +1172,12 @@ module ActiveRecord
1117
1172
  def add_index_options(table_name, column_name, comment: nil, **options) # :nodoc:
1118
1173
  column_names = index_column_names(column_name)
1119
1174
 
1120
- options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type)
1175
+ options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type, :opclass)
1121
1176
 
1122
1177
  index_type = options[:type].to_s if options.key?(:type)
1123
1178
  index_type ||= options[:unique] ? "UNIQUE" : ""
1124
1179
  index_name = options[:name].to_s if options.key?(:name)
1125
1180
  index_name ||= index_name(table_name, column_names)
1126
- max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
1127
1181
 
1128
1182
  if options.key?(:algorithm)
1129
1183
  algorithm = index_algorithms.fetch(options[:algorithm]) {
@@ -1137,10 +1191,9 @@ module ActiveRecord
1137
1191
  index_options = options[:where] ? " WHERE #{options[:where]}" : ""
1138
1192
  end
1139
1193
 
1140
- if index_name.length > max_index_length
1141
- raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{max_index_length} characters"
1142
- end
1143
- if data_source_exists?(table_name) && index_name_exists?(table_name, index_name, false)
1194
+ validate_index_length!(table_name, index_name, options.fetch(:internal, false))
1195
+
1196
+ if data_source_exists?(table_name) && index_name_exists?(table_name, index_name)
1144
1197
  raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
1145
1198
  end
1146
1199
  index_columns = quoted_columns_for_index(column_names, options).join(", ")
@@ -1153,32 +1206,51 @@ module ActiveRecord
1153
1206
  end
1154
1207
 
1155
1208
  # Changes the comment for a table or removes it if +nil+.
1156
- def change_table_comment(table_name, comment)
1209
+ #
1210
+ # Passing a hash containing +:from+ and +:to+ will make this change
1211
+ # reversible in migration:
1212
+ #
1213
+ # change_table_comment(:posts, from: "old_comment", to: "new_comment")
1214
+ def change_table_comment(table_name, comment_or_changes)
1157
1215
  raise NotImplementedError, "#{self.class} does not support changing table comments"
1158
1216
  end
1159
1217
 
1160
1218
  # Changes the comment for a column or removes it if +nil+.
1161
- def change_column_comment(table_name, column_name, comment) #:nodoc:
1219
+ #
1220
+ # Passing a hash containing +:from+ and +:to+ will make this change
1221
+ # reversible in migration:
1222
+ #
1223
+ # change_column_comment(:posts, :state, from: "old_comment", to: "new_comment")
1224
+ def change_column_comment(table_name, column_name, comment_or_changes)
1162
1225
  raise NotImplementedError, "#{self.class} does not support changing column comments"
1163
1226
  end
1164
1227
 
1165
- protected
1228
+ def create_schema_dumper(options) # :nodoc:
1229
+ SchemaDumper.create(self, options)
1230
+ end
1231
+
1232
+ private
1233
+ def column_options_keys
1234
+ [:limit, :precision, :scale, :default, :null, :collation, :comment]
1235
+ end
1166
1236
 
1167
1237
  def add_index_sort_order(quoted_columns, **options)
1168
- if order = options[:order]
1169
- case order
1170
- when Hash
1171
- order = order.symbolize_keys
1172
- quoted_columns.each { |name, column| column << " #{order[name].upcase}" if order[name].present? }
1173
- when String
1174
- quoted_columns.each { |name, column| column << " #{order.upcase}" if order.present? }
1175
- end
1238
+ orders = options_for_index_columns(options[:order])
1239
+ quoted_columns.each do |name, column|
1240
+ column << " #{orders[name].upcase}" if orders[name].present?
1176
1241
  end
1242
+ end
1177
1243
 
1178
- quoted_columns
1244
+ def options_for_index_columns(options)
1245
+ if options.is_a?(Hash)
1246
+ options.symbolize_keys
1247
+ else
1248
+ Hash.new { |hash, column| hash[column] = options }
1249
+ end
1179
1250
  end
1180
1251
 
1181
- # Overridden by the MySQL adapter for supporting index lengths
1252
+ # Overridden by the MySQL adapter for supporting index lengths and by
1253
+ # the PostgreSQL adapter for supporting operator classes.
1182
1254
  def add_options_for_index_columns(quoted_columns, **options)
1183
1255
  if supports_index_sort_order?
1184
1256
  quoted_columns = add_index_sort_order(quoted_columns, options)
@@ -1197,10 +1269,6 @@ module ActiveRecord
1197
1269
  def index_name_for_remove(table_name, options = {})
1198
1270
  return options[:name] if can_remove_index_by_name?(options)
1199
1271
 
1200
- # if the adapter doesn't support the indexes call the best we can do
1201
- # is return the default index name for the options provided
1202
- return index_name(table_name, options) unless respond_to?(:indexes)
1203
-
1204
1272
  checks = []
1205
1273
 
1206
1274
  if options.is_a?(Hash)
@@ -1250,56 +1318,158 @@ module ActiveRecord
1250
1318
  end
1251
1319
  end
1252
1320
 
1253
- private
1254
- def create_table_definition(*args)
1255
- TableDefinition.new(*args)
1256
- end
1321
+ def schema_creation
1322
+ SchemaCreation.new(self)
1323
+ end
1257
1324
 
1258
- def create_alter_table(name)
1259
- AlterTable.new create_table_definition(name)
1260
- end
1325
+ def create_table_definition(*args)
1326
+ TableDefinition.new(self, *args)
1327
+ end
1261
1328
 
1262
- def index_column_names(column_names)
1263
- if column_names.is_a?(String) && /\W/ === column_names
1264
- column_names
1265
- else
1266
- Array(column_names)
1329
+ def create_alter_table(name)
1330
+ AlterTable.new create_table_definition(name)
1267
1331
  end
1268
- end
1269
1332
 
1270
- def index_name_options(column_names) # :nodoc:
1271
- if column_names.is_a?(String) && /\W/ === column_names
1272
- column_names = column_names.scan(/\w+/).join('_')
1333
+ def fetch_type_metadata(sql_type)
1334
+ cast_type = lookup_cast_type(sql_type)
1335
+ SqlTypeMetadata.new(
1336
+ sql_type: sql_type,
1337
+ type: cast_type.type,
1338
+ limit: cast_type.limit,
1339
+ precision: cast_type.precision,
1340
+ scale: cast_type.scale,
1341
+ )
1273
1342
  end
1274
1343
 
1275
- { column: column_names }
1276
- end
1344
+ def index_column_names(column_names)
1345
+ if column_names.is_a?(String) && /\W/.match?(column_names)
1346
+ column_names
1347
+ else
1348
+ Array(column_names)
1349
+ end
1350
+ end
1351
+
1352
+ def index_name_options(column_names)
1353
+ if column_names.is_a?(String) && /\W/.match?(column_names)
1354
+ column_names = column_names.scan(/\w+/).join("_")
1355
+ end
1277
1356
 
1278
- def foreign_key_name(table_name, options) # :nodoc:
1279
- identifier = "#{table_name}_#{options.fetch(:column)}_fk"
1280
- hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
1281
- options.fetch(:name) do
1282
- "fk_rails_#{hashed_identifier}"
1357
+ { column: column_names }
1283
1358
  end
1284
- end
1285
1359
 
1286
- def validate_index_length!(table_name, new_name) # :nodoc:
1287
- if new_name.length > allowed_index_name_length
1288
- raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters"
1360
+ def strip_table_name_prefix_and_suffix(table_name)
1361
+ prefix = Base.table_name_prefix
1362
+ suffix = Base.table_name_suffix
1363
+ table_name.to_s =~ /#{prefix}(.+)#{suffix}/ ? $1 : table_name.to_s
1289
1364
  end
1290
- end
1291
1365
 
1292
- def extract_new_default_value(default_or_changes)
1293
- if default_or_changes.is_a?(Hash) && default_or_changes.has_key?(:from) && default_or_changes.has_key?(:to)
1294
- default_or_changes[:to]
1295
- else
1296
- default_or_changes
1366
+ def foreign_key_name(table_name, options)
1367
+ options.fetch(:name) do
1368
+ identifier = "#{table_name}_#{options.fetch(:column)}_fk"
1369
+ hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
1370
+
1371
+ "fk_rails_#{hashed_identifier}"
1372
+ end
1297
1373
  end
1298
- end
1299
1374
 
1300
- def can_remove_index_by_name?(options)
1301
- options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
1302
- end
1375
+ def foreign_key_for(from_table, **options)
1376
+ return unless supports_foreign_keys?
1377
+ foreign_keys(from_table).detect { |fk| fk.defined_for?(options) }
1378
+ end
1379
+
1380
+ def foreign_key_for!(from_table, to_table: nil, **options)
1381
+ foreign_key_for(from_table, to_table: to_table, **options) ||
1382
+ raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{to_table || options}")
1383
+ end
1384
+
1385
+ def extract_foreign_key_action(specifier)
1386
+ case specifier
1387
+ when "CASCADE"; :cascade
1388
+ when "SET NULL"; :nullify
1389
+ when "RESTRICT"; :restrict
1390
+ end
1391
+ end
1392
+
1393
+ def validate_index_length!(table_name, new_name, internal = false)
1394
+ max_index_length = internal ? index_name_length : allowed_index_name_length
1395
+
1396
+ if new_name.length > max_index_length
1397
+ raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters"
1398
+ end
1399
+ end
1400
+
1401
+ def extract_new_default_value(default_or_changes)
1402
+ if default_or_changes.is_a?(Hash) && default_or_changes.has_key?(:from) && default_or_changes.has_key?(:to)
1403
+ default_or_changes[:to]
1404
+ else
1405
+ default_or_changes
1406
+ end
1407
+ end
1408
+ alias :extract_new_comment_value :extract_new_default_value
1409
+
1410
+ def can_remove_index_by_name?(options)
1411
+ options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
1412
+ end
1413
+
1414
+ def bulk_change_table(table_name, operations)
1415
+ sql_fragments = []
1416
+ non_combinable_operations = []
1417
+
1418
+ operations.each do |command, args|
1419
+ table, arguments = args.shift, args
1420
+ method = :"#{command}_for_alter"
1421
+
1422
+ if respond_to?(method, true)
1423
+ sqls, procs = Array(send(method, table, *arguments)).partition { |v| v.is_a?(String) }
1424
+ sql_fragments << sqls
1425
+ non_combinable_operations.concat(procs)
1426
+ else
1427
+ execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
1428
+ non_combinable_operations.each(&:call)
1429
+ sql_fragments = []
1430
+ non_combinable_operations = []
1431
+ send(command, table, *arguments)
1432
+ end
1433
+ end
1434
+
1435
+ execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
1436
+ non_combinable_operations.each(&:call)
1437
+ end
1438
+
1439
+ def add_column_for_alter(table_name, column_name, type, options = {})
1440
+ td = create_table_definition(table_name)
1441
+ cd = td.new_column_definition(column_name, type, options)
1442
+ schema_creation.accept(AddColumnDefinition.new(cd))
1443
+ end
1444
+
1445
+ def remove_column_for_alter(table_name, column_name, type = nil, options = {})
1446
+ "DROP COLUMN #{quote_column_name(column_name)}"
1447
+ end
1448
+
1449
+ def remove_columns_for_alter(table_name, *column_names)
1450
+ column_names.map { |column_name| remove_column_for_alter(table_name, column_name) }
1451
+ end
1452
+
1453
+ def insert_versions_sql(versions)
1454
+ sm_table = quote_table_name(schema_migration.table_name)
1455
+
1456
+ if versions.is_a?(Array)
1457
+ sql = +"INSERT INTO #{sm_table} (version) VALUES\n"
1458
+ sql << versions.map { |v| "(#{quote(v)})" }.join(",\n")
1459
+ sql << ";\n\n"
1460
+ sql
1461
+ else
1462
+ "INSERT INTO #{sm_table} (version) VALUES (#{quote(versions)});"
1463
+ end
1464
+ end
1465
+
1466
+ def data_source_sql(name = nil, type: nil)
1467
+ raise NotImplementedError
1468
+ end
1469
+
1470
+ def quoted_scope(name = nil, type: nil)
1471
+ raise NotImplementedError
1472
+ end
1303
1473
  end
1304
1474
  end
1305
1475
  end