activerecord 5.0.7 → 5.1.7

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 (219) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +657 -2080
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +28 -28
  6. data/examples/simple.rb +3 -3
  7. data/lib/active_record/aggregations.rb +244 -244
  8. data/lib/active_record/association_relation.rb +5 -5
  9. data/lib/active_record/associations/alias_tracker.rb +10 -11
  10. data/lib/active_record/associations/association.rb +23 -5
  11. data/lib/active_record/associations/association_scope.rb +95 -81
  12. data/lib/active_record/associations/belongs_to_association.rb +7 -4
  13. data/lib/active_record/associations/builder/belongs_to.rb +30 -16
  14. data/lib/active_record/associations/builder/collection_association.rb +1 -2
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
  16. data/lib/active_record/associations/collection_association.rb +36 -205
  17. data/lib/active_record/associations/collection_proxy.rb +132 -63
  18. data/lib/active_record/associations/has_many_association.rb +10 -19
  19. data/lib/active_record/associations/has_many_through_association.rb +12 -4
  20. data/lib/active_record/associations/has_one_association.rb +24 -28
  21. data/lib/active_record/associations/has_one_through_association.rb +5 -1
  22. data/lib/active_record/associations/join_dependency/join_association.rb +4 -28
  23. data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
  24. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  25. data/lib/active_record/associations/join_dependency.rb +121 -118
  26. data/lib/active_record/associations/preloader/association.rb +64 -64
  27. data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
  28. data/lib/active_record/associations/preloader/collection_association.rb +6 -6
  29. data/lib/active_record/associations/preloader/has_many.rb +0 -2
  30. data/lib/active_record/associations/preloader/singular_association.rb +6 -8
  31. data/lib/active_record/associations/preloader/through_association.rb +41 -41
  32. data/lib/active_record/associations/preloader.rb +94 -94
  33. data/lib/active_record/associations/singular_association.rb +8 -25
  34. data/lib/active_record/associations/through_association.rb +2 -5
  35. data/lib/active_record/associations.rb +1591 -1562
  36. data/lib/active_record/attribute/user_provided_default.rb +4 -2
  37. data/lib/active_record/attribute.rb +98 -71
  38. data/lib/active_record/attribute_assignment.rb +61 -61
  39. data/lib/active_record/attribute_decorators.rb +35 -13
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
  41. data/lib/active_record/attribute_methods/dirty.rb +229 -46
  42. data/lib/active_record/attribute_methods/primary_key.rb +74 -73
  43. data/lib/active_record/attribute_methods/read.rb +39 -35
  44. data/lib/active_record/attribute_methods/serialization.rb +7 -7
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
  46. data/lib/active_record/attribute_methods/write.rb +30 -33
  47. data/lib/active_record/attribute_methods.rb +56 -65
  48. data/lib/active_record/attribute_mutation_tracker.rb +63 -11
  49. data/lib/active_record/attribute_set/builder.rb +27 -33
  50. data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
  51. data/lib/active_record/attribute_set.rb +9 -6
  52. data/lib/active_record/attributes.rb +22 -22
  53. data/lib/active_record/autosave_association.rb +18 -13
  54. data/lib/active_record/base.rb +24 -22
  55. data/lib/active_record/callbacks.rb +56 -14
  56. data/lib/active_record/coders/yaml_column.rb +9 -11
  57. data/lib/active_record/collection_cache_key.rb +3 -4
  58. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +330 -284
  59. data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
  60. data/lib/active_record/connection_adapters/abstract/database_statements.rb +39 -37
  61. data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -27
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -51
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +10 -20
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +74 -79
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +120 -100
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +49 -43
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -135
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +404 -424
  70. data/lib/active_record/connection_adapters/column.rb +26 -4
  71. data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
  72. data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -28
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +7 -6
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +23 -27
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +32 -53
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +19 -9
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
  91. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +0 -10
  92. data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
  93. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
  96. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +32 -30
  97. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
  99. data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
  100. data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -35
  101. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
  103. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
  104. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +182 -222
  105. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +6 -4
  106. data/lib/active_record/connection_adapters/postgresql/utils.rb +7 -5
  107. data/lib/active_record/connection_adapters/postgresql_adapter.rb +198 -167
  108. data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
  109. data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
  110. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
  111. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -19
  112. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
  113. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
  114. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
  115. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +32 -0
  116. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +184 -167
  117. data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
  118. data/lib/active_record/connection_handling.rb +14 -26
  119. data/lib/active_record/core.rb +109 -93
  120. data/lib/active_record/counter_cache.rb +60 -13
  121. data/lib/active_record/define_callbacks.rb +20 -0
  122. data/lib/active_record/dynamic_matchers.rb +80 -79
  123. data/lib/active_record/enum.rb +8 -6
  124. data/lib/active_record/errors.rb +64 -15
  125. data/lib/active_record/explain.rb +1 -2
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +7 -4
  128. data/lib/active_record/fixture_set/file.rb +11 -8
  129. data/lib/active_record/fixtures.rb +66 -53
  130. data/lib/active_record/gem_version.rb +1 -1
  131. data/lib/active_record/inheritance.rb +93 -79
  132. data/lib/active_record/integration.rb +7 -7
  133. data/lib/active_record/internal_metadata.rb +3 -16
  134. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  135. data/lib/active_record/locking/optimistic.rb +69 -74
  136. data/lib/active_record/locking/pessimistic.rb +10 -1
  137. data/lib/active_record/log_subscriber.rb +23 -28
  138. data/lib/active_record/migration/command_recorder.rb +94 -94
  139. data/lib/active_record/migration/compatibility.rb +100 -47
  140. data/lib/active_record/migration/join_table.rb +6 -6
  141. data/lib/active_record/migration.rb +153 -155
  142. data/lib/active_record/model_schema.rb +94 -107
  143. data/lib/active_record/nested_attributes.rb +200 -199
  144. data/lib/active_record/null_relation.rb +11 -34
  145. data/lib/active_record/persistence.rb +65 -50
  146. data/lib/active_record/query_cache.rb +2 -6
  147. data/lib/active_record/querying.rb +3 -4
  148. data/lib/active_record/railtie.rb +16 -17
  149. data/lib/active_record/railties/controller_runtime.rb +6 -2
  150. data/lib/active_record/railties/databases.rake +105 -133
  151. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  152. data/lib/active_record/readonly_attributes.rb +2 -2
  153. data/lib/active_record/reflection.rb +154 -108
  154. data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
  155. data/lib/active_record/relation/batches.rb +80 -51
  156. data/lib/active_record/relation/calculations.rb +169 -162
  157. data/lib/active_record/relation/delegation.rb +32 -31
  158. data/lib/active_record/relation/finder_methods.rb +197 -231
  159. data/lib/active_record/relation/merger.rb +58 -62
  160. data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
  161. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
  162. data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
  163. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
  165. data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
  166. data/lib/active_record/relation/predicate_builder.rb +92 -89
  167. data/lib/active_record/relation/query_attribute.rb +1 -1
  168. data/lib/active_record/relation/query_methods.rb +255 -293
  169. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  170. data/lib/active_record/relation/spawn_methods.rb +4 -5
  171. data/lib/active_record/relation/where_clause.rb +80 -65
  172. data/lib/active_record/relation/where_clause_factory.rb +47 -8
  173. data/lib/active_record/relation.rb +93 -119
  174. data/lib/active_record/result.rb +41 -32
  175. data/lib/active_record/runtime_registry.rb +3 -3
  176. data/lib/active_record/sanitization.rb +176 -192
  177. data/lib/active_record/schema.rb +3 -3
  178. data/lib/active_record/schema_dumper.rb +15 -38
  179. data/lib/active_record/schema_migration.rb +8 -4
  180. data/lib/active_record/scoping/default.rb +90 -90
  181. data/lib/active_record/scoping/named.rb +11 -11
  182. data/lib/active_record/scoping.rb +6 -6
  183. data/lib/active_record/secure_token.rb +2 -2
  184. data/lib/active_record/statement_cache.rb +13 -15
  185. data/lib/active_record/store.rb +31 -32
  186. data/lib/active_record/suppressor.rb +2 -1
  187. data/lib/active_record/table_metadata.rb +9 -5
  188. data/lib/active_record/tasks/database_tasks.rb +65 -55
  189. data/lib/active_record/tasks/mysql_database_tasks.rb +76 -73
  190. data/lib/active_record/tasks/postgresql_database_tasks.rb +72 -47
  191. data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
  192. data/lib/active_record/timestamp.rb +46 -25
  193. data/lib/active_record/touch_later.rb +1 -2
  194. data/lib/active_record/transactions.rb +97 -109
  195. data/lib/active_record/type/adapter_specific_registry.rb +46 -42
  196. data/lib/active_record/type/decimal_without_scale.rb +13 -0
  197. data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
  198. data/lib/active_record/type/internal/abstract_json.rb +4 -0
  199. data/lib/active_record/type/serialized.rb +14 -8
  200. data/lib/active_record/type/text.rb +9 -0
  201. data/lib/active_record/type/time.rb +0 -1
  202. data/lib/active_record/type/type_map.rb +11 -15
  203. data/lib/active_record/type/unsigned_integer.rb +15 -0
  204. data/lib/active_record/type.rb +17 -13
  205. data/lib/active_record/type_caster/connection.rb +8 -6
  206. data/lib/active_record/type_caster/map.rb +3 -1
  207. data/lib/active_record/type_caster.rb +2 -2
  208. data/lib/active_record/validations/associated.rb +1 -1
  209. data/lib/active_record/validations/presence.rb +2 -2
  210. data/lib/active_record/validations/uniqueness.rb +8 -39
  211. data/lib/active_record/validations.rb +4 -4
  212. data/lib/active_record/version.rb +1 -1
  213. data/lib/active_record.rb +20 -20
  214. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
  215. data/lib/rails/generators/active_record/migration.rb +1 -1
  216. data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
  217. data/lib/rails/generators/active_record.rb +4 -4
  218. metadata +24 -13
  219. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -1,6 +1,6 @@
1
- require 'active_record/migration/join_table'
2
- require 'active_support/core_ext/string/access'
3
- require 'digest'
1
+ require "active_record/migration/join_table"
2
+ require "active_support/core_ext/string/access"
3
+ require "digest"
4
4
 
5
5
  module ActiveRecord
6
6
  module ConnectionAdapters # :nodoc:
@@ -25,12 +25,14 @@ module ActiveRecord
25
25
 
26
26
  # Truncates a table alias according to the limits of the current adapter.
27
27
  def table_alias_for(table_name)
28
- table_name[0...table_alias_length].tr('.', '_')
28
+ table_name[0...table_alias_length].tr(".", "_")
29
29
  end
30
30
 
31
31
  # Returns the relation names useable to back Active Record models.
32
32
  # For most adapters this means all #tables and #views.
33
33
  def data_sources
34
+ query_values(data_source_sql, "SCHEMA")
35
+ rescue NotImplementedError
34
36
  tables | views
35
37
  end
36
38
 
@@ -39,12 +41,14 @@ module ActiveRecord
39
41
  # data_source_exists?(:ebooks)
40
42
  #
41
43
  def data_source_exists?(name)
44
+ query_values(data_source_sql(name), "SCHEMA").any? if name.present?
45
+ rescue NotImplementedError
42
46
  data_sources.include?(name.to_s)
43
47
  end
44
48
 
45
49
  # Returns an array of table names defined in the database.
46
- def tables(name = nil)
47
- raise NotImplementedError, "#tables is not implemented"
50
+ def tables
51
+ query_values(data_source_sql(type: "BASE TABLE"), "SCHEMA")
48
52
  end
49
53
 
50
54
  # Checks to see if the table +table_name+ exists on the database.
@@ -52,12 +56,14 @@ module ActiveRecord
52
56
  # table_exists?(:developers)
53
57
  #
54
58
  def table_exists?(table_name)
59
+ query_values(data_source_sql(table_name, type: "BASE TABLE"), "SCHEMA").any? if table_name.present?
60
+ rescue NotImplementedError
55
61
  tables.include?(table_name.to_s)
56
62
  end
57
63
 
58
64
  # Returns an array of view names defined in the database.
59
65
  def views
60
- raise NotImplementedError, "#views is not implemented"
66
+ query_values(data_source_sql(type: "VIEW"), "SCHEMA")
61
67
  end
62
68
 
63
69
  # Checks to see if the view +view_name+ exists on the database.
@@ -65,11 +71,15 @@ module ActiveRecord
65
71
  # view_exists?(:ebooks)
66
72
  #
67
73
  def view_exists?(view_name)
74
+ query_values(data_source_sql(view_name, type: "VIEW"), "SCHEMA").any? if view_name.present?
75
+ rescue NotImplementedError
68
76
  views.include?(view_name.to_s)
69
77
  end
70
78
 
71
79
  # Returns an array of indexes for the given table.
72
- # def indexes(table_name, name = nil) end
80
+ def indexes(table_name, name = nil)
81
+ raise NotImplementedError, "#indexes is not implemented"
82
+ end
73
83
 
74
84
  # Checks to see if an index exists on a table for a given index definition.
75
85
  #
@@ -120,7 +130,7 @@ module ActiveRecord
120
130
  checks = []
121
131
  checks << lambda { |c| c.name == column_name }
122
132
  checks << lambda { |c| c.type == type } if type
123
- (migration_keys - [:name]).each do |attr|
133
+ column_options_keys.each do |attr|
124
134
  checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
125
135
  end
126
136
 
@@ -174,7 +184,7 @@ module ActiveRecord
174
184
  # A Symbol can be used to specify the type of the generated primary key column.
175
185
  # [<tt>:primary_key</tt>]
176
186
  # 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.
187
+ # Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored.
178
188
  #
179
189
  # Note that Active Record models will automatically detect their
180
190
  # primary key. This can be avoided by using
@@ -271,8 +281,8 @@ module ActiveRecord
271
281
 
272
282
  yield td if block_given?
273
283
 
274
- if options[:force] && data_source_exists?(table_name)
275
- drop_table(table_name, options)
284
+ if options[:force]
285
+ drop_table(table_name, **options, if_exists: true)
276
286
  end
277
287
 
278
288
  result = execute schema_creation.accept td
@@ -300,9 +310,9 @@ module ActiveRecord
300
310
  # # Creates a table called 'assemblies_parts' with no id.
301
311
  # create_join_table(:assemblies, :parts)
302
312
  #
303
- # You can pass a +options+ hash can include the following keys:
313
+ # You can pass an +options+ hash which can include the following keys:
304
314
  # [<tt>:table_name</tt>]
305
- # Sets the table name overriding the default
315
+ # Sets the table name, overriding the default.
306
316
  # [<tt>:column_options</tt>]
307
317
  # Any extra options you want appended to the columns definition.
308
318
  # [<tt>:options</tt>]
@@ -332,18 +342,16 @@ module ActiveRecord
332
342
  # part_id int NOT NULL,
333
343
  # ) ENGINE=InnoDB DEFAULT CHARSET=utf8
334
344
  #
335
- def create_join_table(table_1, table_2, options = {})
345
+ def create_join_table(table_1, table_2, column_options: {}, **options)
336
346
  join_table_name = find_join_table_name(table_1, table_2, options)
337
347
 
338
- column_options = options.delete(:column_options) || {}
339
- column_options.reverse_merge!(null: false)
340
- type = column_options.delete(:type) || :integer
348
+ column_options.reverse_merge!(null: false, index: false)
341
349
 
342
- t1_column, t2_column = [table_1, table_2].map{ |t| t.to_s.singularize.foreign_key }
350
+ t1_ref, t2_ref = [table_1, table_2].map { |t| t.to_s.singularize }
343
351
 
344
352
  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
353
+ td.references t1_ref, column_options
354
+ td.references t2_ref, column_options
347
355
  yield td if block_given?
348
356
  end
349
357
  end
@@ -428,7 +436,7 @@ module ActiveRecord
428
436
  # t.remove_index :company_id
429
437
  # end
430
438
  #
431
- # See also Table for details on all of the various column transformation.
439
+ # See also Table for details on all of the various column transformations.
432
440
  def change_table(table_name, options = {})
433
441
  if supports_bulk_alter? && options[:bulk]
434
442
  recorder = ActiveRecord::Migration::CommandRecorder.new(self)
@@ -478,10 +486,10 @@ module ActiveRecord
478
486
  #
479
487
  # Available options are (none of these exists by default):
480
488
  # * <tt>:limit</tt> -
481
- # Requests a maximum column length. This is number of characters for a <tt>:string</tt> column
489
+ # Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
482
490
  # and number of bytes for <tt>:text</tt>, <tt>:binary</tt> and <tt>:integer</tt> columns.
483
491
  # * <tt>:default</tt> -
484
- # The column's default value. Use nil for NULL.
492
+ # The column's default value. Use +nil+ for +NULL+.
485
493
  # * <tt>:null</tt> -
486
494
  # Allows or disallows +NULL+ values in the column. This option could
487
495
  # have been named <tt>:null_allowed</tt>.
@@ -490,7 +498,7 @@ module ActiveRecord
490
498
  # * <tt>:scale</tt> -
491
499
  # Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
492
500
  #
493
- # Note: The precision is the total number of significant digits
501
+ # Note: The precision is the total number of significant digits,
494
502
  # and the scale is the number of digits that can be stored following
495
503
  # the decimal point. For example, the number 123.45 has a precision of 5
496
504
  # and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
@@ -511,7 +519,7 @@ module ActiveRecord
511
519
  # Default is (38,0).
512
520
  # * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
513
521
  # Default unknown.
514
- # * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
522
+ # * SqlServer: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
515
523
  # Default (38,0).
516
524
  #
517
525
  # == Examples
@@ -533,6 +541,10 @@ module ActiveRecord
533
541
  # add_column(:measurements, :huge_integer, :decimal, precision: 30)
534
542
  # # ALTER TABLE "measurements" ADD "huge_integer" decimal(30)
535
543
  #
544
+ # # Defines a column that stores an array of a type.
545
+ # add_column(:users, :skills, :text, array: true)
546
+ # # ALTER TABLE "users" ADD "skills" text[]
547
+ #
536
548
  # # Defines a column with a database-specific type.
537
549
  # add_column(:shapes, :triangle, 'polygon')
538
550
  # # ALTER TABLE "shapes" ADD "triangle" polygon
@@ -559,7 +571,7 @@ module ActiveRecord
559
571
  #
560
572
  # The +type+ and +options+ parameters will be ignored if present. It can be helpful
561
573
  # 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.
574
+ # In that case, +type+ and +options+ will be used by #add_column.
563
575
  def remove_column(table_name, column_name, type = nil, options = {})
564
576
  execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}"
565
577
  end
@@ -767,11 +779,12 @@ module ActiveRecord
767
779
  end
768
780
 
769
781
  # 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)
782
+ def index_name_exists?(table_name, index_name, default = nil)
783
+ unless default.nil?
784
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
785
+ Passing default to #index_name_exists? is deprecated without replacement.
786
+ MSG
787
+ end
775
788
  index_name = index_name.to_s
776
789
  indexes(table_name).detect { |i| i.name == index_name }
777
790
  end
@@ -822,8 +835,8 @@ module ActiveRecord
822
835
  #
823
836
  # add_reference(:products, :supplier, foreign_key: {to_table: :firms})
824
837
  #
825
- def add_reference(table_name, *args)
826
- ReferenceDefinition.new(*args).add_to(update_table_definition(table_name, self))
838
+ def add_reference(table_name, ref_name, **options)
839
+ ReferenceDefinition.new(ref_name, options).add_to(update_table_definition(table_name, self))
827
840
  end
828
841
  alias :add_belongs_to :add_reference
829
842
 
@@ -850,6 +863,7 @@ module ActiveRecord
850
863
  else
851
864
  foreign_key_options = { to_table: reference_name }
852
865
  end
866
+ foreign_key_options[:column] ||= "#{ref_name}_id"
853
867
  remove_foreign_key(table_name, **foreign_key_options)
854
868
  end
855
869
 
@@ -947,13 +961,13 @@ module ActiveRecord
947
961
 
948
962
  # Checks to see if a foreign key exists on a table for a given foreign key definition.
949
963
  #
950
- # # Check a foreign key exists
964
+ # # Checks to see if a foreign key exists.
951
965
  # foreign_key_exists?(:accounts, :branches)
952
966
  #
953
- # # Check a foreign key on a specified column exists
967
+ # # Checks to see if a foreign key on a specified column exists.
954
968
  # foreign_key_exists?(:accounts, column: :owner_id)
955
969
  #
956
- # # Check a foreign key with a custom name exists
970
+ # # Checks to see if a foreign key with a custom name exists.
957
971
  # foreign_key_exists?(:accounts, name: "special_fk_name")
958
972
  #
959
973
  def foreign_key_exists?(from_table, options_or_to_table = {})
@@ -962,12 +976,12 @@ module ActiveRecord
962
976
 
963
977
  def foreign_key_for(from_table, options_or_to_table = {}) # :nodoc:
964
978
  return unless supports_foreign_keys?
965
- foreign_keys(from_table).detect {|fk| fk.defined_for? options_or_to_table }
979
+ foreign_keys(from_table).detect { |fk| fk.defined_for? options_or_to_table }
966
980
  end
967
981
 
968
982
  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}"
983
+ foreign_key_for(from_table, options_or_to_table) || \
984
+ raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{options_or_to_table}")
971
985
  end
972
986
 
973
987
  def foreign_key_column_for(table_name) # :nodoc:
@@ -985,12 +999,12 @@ module ActiveRecord
985
999
  end
986
1000
 
987
1001
  def dump_schema_information #:nodoc:
988
- versions = ActiveRecord::SchemaMigration.order('version').pluck(:version)
1002
+ versions = ActiveRecord::SchemaMigration.all_versions
989
1003
  insert_versions_sql(versions) if versions.any?
990
1004
  end
991
1005
 
992
1006
  def insert_versions_sql(versions) # :nodoc:
993
- sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)
1007
+ sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
994
1008
 
995
1009
  if versions.is_a?(Array)
996
1010
  sql = "INSERT INTO #{sm_table} (version) VALUES\n"
@@ -1002,15 +1016,15 @@ module ActiveRecord
1002
1016
  end
1003
1017
  end
1004
1018
 
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
1019
+ def initialize_schema_migrations_table # :nodoc:
1008
1020
  ActiveRecord::SchemaMigration.create_table
1009
1021
  end
1022
+ deprecate :initialize_schema_migrations_table
1010
1023
 
1011
- def initialize_internal_metadata_table
1024
+ def initialize_internal_metadata_table # :nodoc:
1012
1025
  ActiveRecord::InternalMetadata.create_table
1013
1026
  end
1027
+ deprecate :initialize_internal_metadata_table
1014
1028
 
1015
1029
  def internal_string_options_for_primary_key # :nodoc:
1016
1030
  { primary_key: true }
@@ -1019,9 +1033,9 @@ module ActiveRecord
1019
1033
  def assume_migrated_upto_version(version, migrations_paths)
1020
1034
  migrations_paths = Array(migrations_paths)
1021
1035
  version = version.to_i
1022
- sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)
1036
+ sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
1023
1037
 
1024
- migrated = select_values("SELECT version FROM #{sm_table}").map(&:to_i)
1038
+ migrated = ActiveRecord::SchemaMigration.all_versions.map(&:to_i)
1025
1039
  versions = ActiveRecord::Migrator.migration_files(migrations_paths).map do |file|
1026
1040
  ActiveRecord::Migrator.parse_migration_filename(file).first.to_i
1027
1041
  end
@@ -1030,9 +1044,9 @@ module ActiveRecord
1030
1044
  execute "INSERT INTO #{sm_table} (version) VALUES (#{quote(version)})"
1031
1045
  end
1032
1046
 
1033
- inserting = (versions - migrated).select {|v| v < version}
1047
+ inserting = (versions - migrated).select { |v| v < version }
1034
1048
  if inserting.any?
1035
- if (duplicate = inserting.detect {|v| inserting.count(v) > 1})
1049
+ if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
1036
1050
  raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
1037
1051
  end
1038
1052
  if supports_multi_insert?
@@ -1045,7 +1059,7 @@ module ActiveRecord
1045
1059
  end
1046
1060
  end
1047
1061
 
1048
- def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
1062
+ def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) # :nodoc:
1049
1063
  type = type.to_sym if type
1050
1064
  if native = native_database_types[type]
1051
1065
  column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
@@ -1063,7 +1077,7 @@ module ActiveRecord
1063
1077
  raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale is specified"
1064
1078
  end
1065
1079
 
1066
- elsif [:datetime, :time].include?(type) && precision ||= native[:precision]
1080
+ elsif [:datetime, :timestamp, :time, :interval].include?(type) && precision ||= native[:precision]
1067
1081
  if (0..6) === precision
1068
1082
  column_type_sql << "(#{precision})"
1069
1083
  else
@@ -1080,7 +1094,7 @@ module ActiveRecord
1080
1094
  end
1081
1095
 
1082
1096
  # 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
1097
+ # PostgreSQL, MySQL, and Oracle override this for custom DISTINCT syntax - they
1084
1098
  # require the order columns appear in the SELECT.
1085
1099
  #
1086
1100
  # columns_for_distinct("posts.id", ["posts.created_at desc"])
@@ -1123,7 +1137,6 @@ module ActiveRecord
1123
1137
  index_type ||= options[:unique] ? "UNIQUE" : ""
1124
1138
  index_name = options[:name].to_s if options.key?(:name)
1125
1139
  index_name ||= index_name(table_name, column_names)
1126
- max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
1127
1140
 
1128
1141
  if options.key?(:algorithm)
1129
1142
  algorithm = index_algorithms.fetch(options[:algorithm]) {
@@ -1137,10 +1150,9 @@ module ActiveRecord
1137
1150
  index_options = options[:where] ? " WHERE #{options[:where]}" : ""
1138
1151
  end
1139
1152
 
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)
1153
+ validate_index_length!(table_name, index_name, options.fetch(:internal, false))
1154
+
1155
+ if data_source_exists?(table_name) && index_name_exists?(table_name, index_name)
1144
1156
  raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
1145
1157
  end
1146
1158
  index_columns = quoted_columns_for_index(column_names, options).join(", ")
@@ -1162,7 +1174,10 @@ module ActiveRecord
1162
1174
  raise NotImplementedError, "#{self.class} does not support changing column comments"
1163
1175
  end
1164
1176
 
1165
- protected
1177
+ private
1178
+ def column_options_keys
1179
+ [:limit, :precision, :scale, :default, :null, :collation, :comment]
1180
+ end
1166
1181
 
1167
1182
  def add_index_sort_order(quoted_columns, **options)
1168
1183
  if order = options[:order]
@@ -1197,10 +1212,6 @@ module ActiveRecord
1197
1212
  def index_name_for_remove(table_name, options = {})
1198
1213
  return options[:name] if can_remove_index_by_name?(options)
1199
1214
 
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
1215
  checks = []
1205
1216
 
1206
1217
  if options.is_a?(Hash)
@@ -1250,56 +1261,65 @@ module ActiveRecord
1250
1261
  end
1251
1262
  end
1252
1263
 
1253
- private
1254
- def create_table_definition(*args)
1255
- TableDefinition.new(*args)
1256
- end
1264
+ def create_table_definition(*args)
1265
+ TableDefinition.new(*args)
1266
+ end
1257
1267
 
1258
- def create_alter_table(name)
1259
- AlterTable.new create_table_definition(name)
1260
- end
1268
+ def create_alter_table(name)
1269
+ AlterTable.new create_table_definition(name)
1270
+ end
1261
1271
 
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)
1272
+ def index_column_names(column_names)
1273
+ if column_names.is_a?(String) && /\W/.match?(column_names)
1274
+ column_names
1275
+ else
1276
+ Array(column_names)
1277
+ end
1267
1278
  end
1268
- end
1269
1279
 
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('_')
1280
+ def index_name_options(column_names)
1281
+ if column_names.is_a?(String) && /\W/.match?(column_names)
1282
+ column_names = column_names.scan(/\w+/).join("_")
1283
+ end
1284
+
1285
+ { column: column_names }
1273
1286
  end
1274
1287
 
1275
- { column: column_names }
1276
- end
1288
+ def foreign_key_name(table_name, options)
1289
+ identifier = "#{table_name}_#{options.fetch(:column)}_fk"
1290
+ hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
1291
+ options.fetch(:name) do
1292
+ "fk_rails_#{hashed_identifier}"
1293
+ end
1294
+ end
1277
1295
 
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}"
1296
+ def validate_index_length!(table_name, new_name, internal = false)
1297
+ max_index_length = internal ? index_name_length : allowed_index_name_length
1298
+
1299
+ if new_name.length > max_index_length
1300
+ raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters"
1301
+ end
1283
1302
  end
1284
- end
1285
1303
 
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"
1304
+ def extract_new_default_value(default_or_changes)
1305
+ if default_or_changes.is_a?(Hash) && default_or_changes.has_key?(:from) && default_or_changes.has_key?(:to)
1306
+ default_or_changes[:to]
1307
+ else
1308
+ default_or_changes
1309
+ end
1289
1310
  end
1290
- end
1291
1311
 
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
1312
+ def can_remove_index_by_name?(options)
1313
+ options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
1297
1314
  end
1298
- end
1299
1315
 
1300
- def can_remove_index_by_name?(options)
1301
- options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
1302
- end
1316
+ def data_source_sql(name = nil, type: nil)
1317
+ raise NotImplementedError
1318
+ end
1319
+
1320
+ def quoted_scope(name = nil, type: nil)
1321
+ raise NotImplementedError
1322
+ end
1303
1323
  end
1304
1324
  end
1305
1325
  end
@@ -41,7 +41,6 @@ module ActiveRecord
41
41
  end
42
42
 
43
43
  class Transaction #:nodoc:
44
-
45
44
  attr_reader :connection, :state, :records, :savepoint_name
46
45
  attr_writer :joinable
47
46
 
@@ -101,7 +100,6 @@ module ActiveRecord
101
100
  end
102
101
 
103
102
  class SavepointTransaction < Transaction
104
-
105
103
  def initialize(connection, savepoint_name, options, *args)
106
104
  super(connection, options, *args)
107
105
  if options[:isolation]
@@ -124,7 +122,6 @@ module ActiveRecord
124
122
  end
125
123
 
126
124
  class RealTransaction < Transaction
127
-
128
125
  def initialize(connection, options, *args)
129
126
  super
130
127
  if options[:isolation]
@@ -152,57 +149,67 @@ module ActiveRecord
152
149
  end
153
150
 
154
151
  def begin_transaction(options = {})
155
- run_commit_callbacks = !current_transaction.joinable?
156
- transaction =
157
- if @stack.empty?
158
- RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
159
- else
160
- SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options,
161
- run_commit_callbacks: run_commit_callbacks)
162
- end
152
+ @connection.lock.synchronize do
153
+ run_commit_callbacks = !current_transaction.joinable?
154
+ transaction =
155
+ if @stack.empty?
156
+ RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
157
+ else
158
+ SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options,
159
+ run_commit_callbacks: run_commit_callbacks)
160
+ end
163
161
 
164
- @stack.push(transaction)
165
- transaction
162
+ @stack.push(transaction)
163
+ transaction
164
+ end
166
165
  end
167
166
 
168
167
  def commit_transaction
169
- transaction = @stack.last
168
+ @connection.lock.synchronize do
169
+ transaction = @stack.last
170
170
 
171
- begin
172
- transaction.before_commit_records
173
- ensure
174
- @stack.pop
175
- end
171
+ begin
172
+ transaction.before_commit_records
173
+ ensure
174
+ @stack.pop
175
+ end
176
176
 
177
- transaction.commit
178
- transaction.commit_records
177
+ transaction.commit
178
+ transaction.commit_records
179
+ end
179
180
  end
180
181
 
181
182
  def rollback_transaction(transaction = nil)
182
- transaction ||= @stack.pop
183
- transaction.rollback
184
- transaction.rollback_records
183
+ @connection.lock.synchronize do
184
+ transaction ||= @stack.pop
185
+ transaction.rollback
186
+ transaction.rollback_records
187
+ end
185
188
  end
186
189
 
187
190
  def within_new_transaction(options = {})
188
- transaction = begin_transaction options
189
- yield
190
- rescue Exception => error
191
- if transaction
192
- rollback_transaction
193
- after_failure_actions(transaction, error)
194
- end
195
- raise
196
- ensure
197
- unless error
198
- if Thread.current.status == 'aborting'
199
- rollback_transaction if transaction
200
- else
201
- begin
202
- commit_transaction
203
- rescue Exception
204
- rollback_transaction(transaction) unless transaction.state.completed?
205
- raise
191
+ @connection.lock.synchronize do
192
+ begin
193
+ transaction = begin_transaction options
194
+ yield
195
+ rescue Exception => error
196
+ if transaction
197
+ rollback_transaction
198
+ after_failure_actions(transaction, error)
199
+ end
200
+ raise
201
+ ensure
202
+ unless error
203
+ if Thread.current.status == "aborting"
204
+ rollback_transaction if transaction
205
+ else
206
+ begin
207
+ commit_transaction
208
+ rescue Exception
209
+ rollback_transaction(transaction) unless transaction.state.completed?
210
+ raise
211
+ end
212
+ end
206
213
  end
207
214
  end
208
215
  end
@@ -226,7 +233,6 @@ module ActiveRecord
226
233
  return unless error.is_a?(ActiveRecord::PreparedStatementCacheExpired)
227
234
  @connection.clear_cache!
228
235
  end
229
-
230
236
  end
231
237
  end
232
238
  end