activerecord 5.0.0.1 → 5.0.1.rc1

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +196 -2
  3. data/README.rdoc +1 -1
  4. data/lib/active_record.rb +1 -1
  5. data/lib/active_record/aggregations.rb +4 -2
  6. data/lib/active_record/association_relation.rb +4 -1
  7. data/lib/active_record/associations.rb +5 -0
  8. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +4 -2
  9. data/lib/active_record/associations/builder/singular_association.rb +10 -1
  10. data/lib/active_record/associations/collection_association.rb +22 -17
  11. data/lib/active_record/associations/collection_proxy.rb +20 -7
  12. data/lib/active_record/associations/has_many_through_association.rb +4 -0
  13. data/lib/active_record/associations/join_dependency.rb +10 -4
  14. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  15. data/lib/active_record/associations/preloader/association.rb +18 -4
  16. data/lib/active_record/associations/preloader/collection_association.rb +0 -1
  17. data/lib/active_record/associations/preloader/singular_association.rb +0 -1
  18. data/lib/active_record/associations/singular_association.rb +8 -2
  19. data/lib/active_record/attribute.rb +3 -3
  20. data/lib/active_record/attribute_methods.rb +3 -7
  21. data/lib/active_record/attribute_methods/primary_key.rb +14 -1
  22. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
  23. data/lib/active_record/attribute_set.rb +2 -0
  24. data/lib/active_record/attribute_set/builder.rb +29 -7
  25. data/lib/active_record/attributes.rb +3 -3
  26. data/lib/active_record/autosave_association.rb +15 -11
  27. data/lib/active_record/base.rb +1 -1
  28. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +40 -32
  29. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  30. data/lib/active_record/connection_adapters/abstract/query_cache.rb +29 -0
  31. data/lib/active_record/connection_adapters/abstract/quoting.rb +4 -4
  32. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +8 -7
  33. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +37 -33
  34. data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -5
  35. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +42 -45
  36. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  37. data/lib/active_record/connection_adapters/mysql/database_statements.rb +6 -23
  38. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  39. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -5
  40. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -0
  41. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +12 -1
  42. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  43. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  44. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +7 -1
  45. data/lib/active_record/connection_adapters/postgresql_adapter.rb +6 -2
  46. data/lib/active_record/core.rb +3 -1
  47. data/lib/active_record/enum.rb +6 -5
  48. data/lib/active_record/gem_version.rb +2 -2
  49. data/lib/active_record/integration.rb +13 -10
  50. data/lib/active_record/migration.rb +6 -5
  51. data/lib/active_record/model_schema.rb +134 -47
  52. data/lib/active_record/no_touching.rb +4 -0
  53. data/lib/active_record/persistence.rb +10 -4
  54. data/lib/active_record/query_cache.rb +13 -15
  55. data/lib/active_record/querying.rb +3 -3
  56. data/lib/active_record/railties/controller_runtime.rb +1 -1
  57. data/lib/active_record/reflection.rb +8 -0
  58. data/lib/active_record/relation.rb +7 -4
  59. data/lib/active_record/relation/calculations.rb +11 -11
  60. data/lib/active_record/relation/delegation.rb +1 -1
  61. data/lib/active_record/relation/finder_methods.rb +11 -9
  62. data/lib/active_record/relation/query_methods.rb +3 -3
  63. data/lib/active_record/result.rb +7 -1
  64. data/lib/active_record/sanitization.rb +11 -1
  65. data/lib/active_record/schema_dumper.rb +10 -17
  66. data/lib/active_record/scoping/named.rb +1 -1
  67. data/lib/active_record/statement_cache.rb +2 -2
  68. data/lib/active_record/table_metadata.rb +4 -3
  69. data/lib/active_record/touch_later.rb +6 -1
  70. data/lib/active_record/type/internal/abstract_json.rb +5 -1
  71. data/lib/active_record/validations/uniqueness.rb +3 -4
  72. metadata +9 -10
@@ -244,7 +244,7 @@ module ActiveRecord
244
244
  end
245
245
 
246
246
  def reset_transaction #:nodoc:
247
- @transaction_manager = TransactionManager.new(self)
247
+ @transaction_manager = ConnectionAdapters::TransactionManager.new(self)
248
248
  end
249
249
 
250
250
  # Register a record with the current transaction so that its after_commit and after_rollback callbacks
@@ -4,6 +4,9 @@ module ActiveRecord
4
4
  class << self
5
5
  def included(base) #:nodoc:
6
6
  dirties_query_cache base, :insert, :update, :delete, :rollback_to_savepoint, :rollback_db_transaction
7
+
8
+ base.set_callback :checkout, :after, :configure_query_cache!
9
+ base.set_callback :checkin, :after, :disable_query_cache!
7
10
  end
8
11
 
9
12
  def dirties_query_cache(base, *method_names)
@@ -18,6 +21,27 @@ module ActiveRecord
18
21
  end
19
22
  end
20
23
 
24
+ module ConnectionPoolConfiguration
25
+ def initialize(*)
26
+ super
27
+ @query_cache_enabled = Concurrent::Map.new { false }
28
+ end
29
+
30
+ def enable_query_cache!
31
+ @query_cache_enabled[connection_cache_key(Thread.current)] = true
32
+ connection.enable_query_cache! if active_connection?
33
+ end
34
+
35
+ def disable_query_cache!
36
+ @query_cache_enabled.delete connection_cache_key(Thread.current)
37
+ connection.disable_query_cache! if active_connection?
38
+ end
39
+
40
+ def query_cache_enabled
41
+ @query_cache_enabled[connection_cache_key(Thread.current)]
42
+ end
43
+ end
44
+
21
45
  attr_reader :query_cache, :query_cache_enabled
22
46
 
23
47
  def initialize(*)
@@ -41,6 +65,7 @@ module ActiveRecord
41
65
 
42
66
  def disable_query_cache!
43
67
  @query_cache_enabled = false
68
+ clear_query_cache
44
69
  end
45
70
 
46
71
  # Disable the query cache within the block.
@@ -90,6 +115,10 @@ module ActiveRecord
90
115
  def locked?(arel)
91
116
  arel.respond_to?(:locked) && arel.locked
92
117
  end
118
+
119
+ def configure_query_cache!
120
+ enable_query_cache! if pool.query_cache_enabled
121
+ end
93
122
  end
94
123
  end
95
124
  end
@@ -112,19 +112,19 @@ module ActiveRecord
112
112
  end
113
113
 
114
114
  def quoted_true
115
- "'t'"
115
+ "'t'".freeze
116
116
  end
117
117
 
118
118
  def unquoted_true
119
- 't'
119
+ 't'.freeze
120
120
  end
121
121
 
122
122
  def quoted_false
123
- "'f'"
123
+ "'f'".freeze
124
124
  end
125
125
 
126
126
  def unquoted_false
127
- 'f'
127
+ 'f'.freeze
128
128
  end
129
129
 
130
130
  # Quote date/time values for use in SQL input. Includes microseconds
@@ -51,11 +51,12 @@ module ActiveRecord
51
51
  options[:primary_key] != default_primary_key
52
52
  end
53
53
 
54
- def defined_for?(options_or_to_table = {})
55
- if options_or_to_table.is_a?(Hash)
56
- options_or_to_table.all? {|key, value| options[key].to_s == value.to_s }
54
+ def defined_for?(to_table_ord = nil, to_table: nil, **options)
55
+ if to_table_ord
56
+ self.to_table == to_table_ord.to_s
57
57
  else
58
- to_table == options_or_to_table.to_s
58
+ (to_table.nil? || to_table.to_s == self.to_table) &&
59
+ options.all? { |k, v| self.options[k].to_s == v.to_s }
59
60
  end
60
61
  end
61
62
 
@@ -211,7 +212,7 @@ module ActiveRecord
211
212
 
212
213
  def initialize(name, temporary = false, options = nil, as = nil, comment: nil)
213
214
  @columns_hash = {}
214
- @indexes = {}
215
+ @indexes = []
215
216
  @foreign_keys = []
216
217
  @primary_keys = nil
217
218
  @temporary = temporary
@@ -303,7 +304,7 @@ module ActiveRecord
303
304
  # end
304
305
  def column(name, type, options = {})
305
306
  name = name.to_s
306
- type = type.to_sym
307
+ type = type.to_sym if type
307
308
  options = options.dup
308
309
 
309
310
  if @columns_hash[name] && @columns_hash[name].primary_key?
@@ -327,7 +328,7 @@ module ActiveRecord
327
328
  #
328
329
  # index(:account_id, name: 'index_projects_on_account_id')
329
330
  def index(column_name, options = {})
330
- indexes[column_name] = options
331
+ indexes << [column_name, options]
331
332
  end
332
333
 
333
334
  def foreign_key(table_name, options = {}) # :nodoc:
@@ -129,14 +129,9 @@ module ActiveRecord
129
129
 
130
130
  # Returns just a table's primary key
131
131
  def primary_key(table_name)
132
- pks = primary_keys(table_name)
133
- warn <<-WARNING.strip_heredoc if pks.count > 1
134
- WARNING: Rails does not support composite primary key.
135
-
136
- #{table_name} has composite primary key. Composite primary key is ignored.
137
- WARNING
138
-
139
- pks.first if pks.one?
132
+ pk = primary_keys(table_name)
133
+ pk = pk.first unless pk.size > 1
134
+ pk
140
135
  end
141
136
 
142
137
  # Creates a new table with the name +table_name+. +table_name+ may either
@@ -283,16 +278,16 @@ module ActiveRecord
283
278
  result = execute schema_creation.accept td
284
279
 
285
280
  unless supports_indexes_in_create?
286
- td.indexes.each_pair do |column_name, index_options|
281
+ td.indexes.each do |column_name, index_options|
287
282
  add_index(table_name, column_name, index_options)
288
283
  end
289
284
  end
290
285
 
291
286
  if supports_comments? && !supports_comments_in_create?
292
- change_table_comment(table_name, comment) if comment
287
+ change_table_comment(table_name, comment) if comment.present?
293
288
 
294
289
  td.columns.each do |column|
295
- change_column_comment(table_name, column.name, column.comment) if column.comment
290
+ change_column_comment(table_name, column.name, column.comment) if column.comment.present?
296
291
  end
297
292
  end
298
293
 
@@ -790,7 +785,7 @@ module ActiveRecord
790
785
  # [<tt>:type</tt>]
791
786
  # The reference column type. Defaults to +:integer+.
792
787
  # [<tt>:index</tt>]
793
- # Add an appropriate index. Defaults to false.
788
+ # Add an appropriate index. Defaults to true.
794
789
  # See #add_index for usage of this option.
795
790
  # [<tt>:foreign_key</tt>]
796
791
  # Add an appropriate foreign key constraint. Defaults to false.
@@ -847,14 +842,19 @@ module ActiveRecord
847
842
  #
848
843
  # remove_reference(:products, :user, index: true, foreign_key: true)
849
844
  #
850
- def remove_reference(table_name, ref_name, options = {})
851
- if options[:foreign_key]
845
+ def remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options)
846
+ if foreign_key
852
847
  reference_name = Base.pluralize_table_names ? ref_name.to_s.pluralize : ref_name
853
- remove_foreign_key(table_name, reference_name)
848
+ if foreign_key.is_a?(Hash)
849
+ foreign_key_options = foreign_key
850
+ else
851
+ foreign_key_options = { to_table: reference_name }
852
+ end
853
+ remove_foreign_key(table_name, **foreign_key_options)
854
854
  end
855
855
 
856
856
  remove_column(table_name, "#{ref_name}_id")
857
- remove_column(table_name, "#{ref_name}_type") if options[:polymorphic]
857
+ remove_column(table_name, "#{ref_name}_type") if polymorphic
858
858
  end
859
859
  alias :remove_belongs_to :remove_reference
860
860
 
@@ -993,8 +993,8 @@ module ActiveRecord
993
993
  sm_table = ActiveRecord::Migrator.schema_migrations_table_name
994
994
 
995
995
  if supports_multi_insert?
996
- sql = "INSERT INTO #{sm_table} (version) VALUES "
997
- sql << versions.map {|v| "('#{v}')" }.join(', ')
996
+ sql = "INSERT INTO #{sm_table} (version) VALUES\n"
997
+ sql << versions.map {|v| "('#{v}')" }.join(",\n")
998
998
  sql << ";\n\n"
999
999
  sql
1000
1000
  else
@@ -1043,7 +1043,8 @@ module ActiveRecord
1043
1043
  end
1044
1044
 
1045
1045
  def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
1046
- if native = native_database_types[type.to_sym]
1046
+ type = type.to_sym if type
1047
+ if native = native_database_types[type]
1047
1048
  column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
1048
1049
 
1049
1050
  if type == :decimal # ignore limit, use precision and scale
@@ -1163,31 +1164,34 @@ module ActiveRecord
1163
1164
  end
1164
1165
 
1165
1166
  protected
1166
- def add_index_sort_order(option_strings, column_names, options = {})
1167
- if options.is_a?(Hash) && order = options[:order]
1167
+
1168
+ def add_index_sort_order(quoted_columns, **options)
1169
+ if order = options[:order]
1168
1170
  case order
1169
1171
  when Hash
1170
- column_names.each {|name| option_strings[name] += " #{order[name].upcase}" if order.has_key?(name)}
1172
+ quoted_columns.each { |name, column| column << " #{order[name].upcase}" if order[name].present? }
1171
1173
  when String
1172
- column_names.each {|name| option_strings[name] += " #{order.upcase}"}
1174
+ quoted_columns.each { |name, column| column << " #{order.upcase}" if order.present? }
1173
1175
  end
1174
1176
  end
1175
1177
 
1176
- return option_strings
1178
+ quoted_columns
1177
1179
  end
1178
1180
 
1179
1181
  # Overridden by the MySQL adapter for supporting index lengths
1180
- def quoted_columns_for_index(column_names, options = {})
1181
- return [column_names] if column_names.is_a?(String)
1182
-
1183
- option_strings = Hash[column_names.map {|name| [name, '']}]
1184
-
1185
- # add index sort order if supported
1182
+ def add_options_for_index_columns(quoted_columns, **options)
1186
1183
  if supports_index_sort_order?
1187
- option_strings = add_index_sort_order(option_strings, column_names, options)
1184
+ quoted_columns = add_index_sort_order(quoted_columns, options)
1188
1185
  end
1189
1186
 
1190
- column_names.map {|name| quote_column_name(name) + option_strings[name]}
1187
+ quoted_columns
1188
+ end
1189
+
1190
+ def quoted_columns_for_index(column_names, **options)
1191
+ return [column_names] if column_names.is_a?(String)
1192
+
1193
+ quoted_columns = Hash[column_names.map { |name| [name.to_sym, quote_column_name(name).dup] }]
1194
+ add_options_for_index_columns(quoted_columns, options).values
1191
1195
  end
1192
1196
 
1193
1197
  def index_name_for_remove(table_name, options = {})
@@ -1210,7 +1214,7 @@ module ActiveRecord
1210
1214
  checks << lambda { |i| i.columns.join('_and_') == column_names.join('_and_') }
1211
1215
  end
1212
1216
 
1213
- raise ArgumentError "No name or columns specified" if checks.none?
1217
+ raise ArgumentError, "No name or columns specified" if checks.none?
1214
1218
 
1215
1219
  matching_indexes = indexes(table_name).select { |i| checks.all? { |check| check[i] } }
1216
1220
 
@@ -61,18 +61,18 @@ module ActiveRecord
61
61
  # Most of the methods in the adapter are useful during migrations. Most
62
62
  # notably, the instance methods provided by SchemaStatements are very useful.
63
63
  class AbstractAdapter
64
- ADAPTER_NAME = 'Abstract'.freeze
64
+ ADAPTER_NAME = "Abstract".freeze
65
+ include ActiveSupport::Callbacks
66
+ define_callbacks :checkout, :checkin
67
+
65
68
  include Quoting, DatabaseStatements, SchemaStatements
66
69
  include DatabaseLimits
67
70
  include QueryCache
68
- include ActiveSupport::Callbacks
69
71
  include ColumnDumper
70
72
  include Savepoints
71
73
 
72
74
  SIMPLE_INT = /\A\d+\z/
73
75
 
74
- define_callbacks :checkout, :checkin
75
-
76
76
  attr_accessor :visitor, :pool
77
77
  attr_reader :schema_cache, :owner, :logger
78
78
  alias :in_use? :owner
@@ -184,7 +184,30 @@ module ActiveRecord
184
184
 
185
185
  # this method must only be called while holding connection pool's mutex
186
186
  def expire
187
- @owner = nil
187
+ if in_use?
188
+ if @owner != Thread.current
189
+ raise ActiveRecordError, "Cannot expire connection, " <<
190
+ "it is owned by a different thread: #{@owner}. " <<
191
+ "Current thread: #{Thread.current}."
192
+ end
193
+
194
+ @owner = nil
195
+ else
196
+ raise ActiveRecordError, 'Cannot expire connection, it is not currently leased.'
197
+ end
198
+ end
199
+
200
+ # this method must only be called while holding connection pool's mutex (and a desire for segfaults)
201
+ def steal! # :nodoc:
202
+ if in_use?
203
+ if @owner != Thread.current
204
+ pool.send :remove_connection_from_thread_cache, self, @owner
205
+
206
+ @owner = Thread.current
207
+ end
208
+ else
209
+ raise ActiveRecordError, 'Cannot steal connection, it is not currently leased.'
210
+ end
188
211
  end
189
212
 
190
213
  def unprepared_statement
@@ -383,11 +383,11 @@ module ActiveRecord
383
383
  mysql_index_type = row[:Index_type].downcase.to_sym
384
384
  index_type = INDEX_TYPES.include?(mysql_index_type) ? mysql_index_type : nil
385
385
  index_using = INDEX_USINGS.include?(mysql_index_type) ? mysql_index_type : nil
386
- indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], [], nil, nil, index_type, index_using, row[:Index_comment].presence)
386
+ indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], {}, nil, nil, index_type, index_using, row[:Index_comment].presence)
387
387
  end
388
388
 
389
389
  indexes.last.columns << row[:Column_name]
390
- indexes.last.lengths << row[:Sub_part]
390
+ indexes.last.lengths.merge!(row[:Column_name] => row[:Sub_part].to_i) if row[:Sub_part]
391
391
  end
392
392
  end
393
393
 
@@ -409,10 +409,13 @@ module ActiveRecord
409
409
  end
410
410
 
411
411
  def table_comment(table_name) # :nodoc:
412
+ schema, name = extract_schema_qualified_name(table_name)
413
+
412
414
  select_value(<<-SQL.strip_heredoc, 'SCHEMA')
413
415
  SELECT table_comment
414
416
  FROM information_schema.tables
415
- WHERE table_name=#{quote(table_name)}
417
+ WHERE table_schema = #{quote(schema)}
418
+ AND table_name = #{quote(name)}
416
419
  SQL
417
420
  end
418
421
 
@@ -460,7 +463,6 @@ module ActiveRecord
460
463
  # it can be helpful to provide these in a migration's +change+ method so it can be reverted.
461
464
  # In that case, +options+ and the block will be used by create_table.
462
465
  def drop_table(table_name, options = {})
463
- create_table_info_cache.delete(table_name) if create_table_info_cache.key?(table_name)
464
466
  execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
465
467
  end
466
468
 
@@ -506,7 +508,7 @@ module ActiveRecord
506
508
  end
507
509
 
508
510
  def add_sql_comment!(sql, comment) # :nodoc:
509
- sql << " COMMENT #{quote(comment)}" if comment
511
+ sql << " COMMENT #{quote(comment)}" if comment.present?
510
512
  sql
511
513
  end
512
514
 
@@ -515,19 +517,21 @@ module ActiveRecord
515
517
 
516
518
  schema, name = extract_schema_qualified_name(table_name)
517
519
 
518
- fk_info = select_all <<-SQL.strip_heredoc
519
- SELECT fk.referenced_table_name as 'to_table'
520
- ,fk.referenced_column_name as 'primary_key'
521
- ,fk.column_name as 'column'
522
- ,fk.constraint_name as 'name'
520
+ fk_info = select_all(<<-SQL.strip_heredoc, 'SCHEMA')
521
+ SELECT fk.referenced_table_name AS 'to_table',
522
+ fk.referenced_column_name AS 'primary_key',
523
+ fk.column_name AS 'column',
524
+ fk.constraint_name AS 'name',
525
+ rc.update_rule AS 'on_update',
526
+ rc.delete_rule AS 'on_delete'
523
527
  FROM information_schema.key_column_usage fk
524
- WHERE fk.referenced_column_name is not null
528
+ JOIN information_schema.referential_constraints rc
529
+ USING (constraint_schema, constraint_name)
530
+ WHERE fk.referenced_column_name IS NOT NULL
525
531
  AND fk.table_schema = #{quote(schema)}
526
532
  AND fk.table_name = #{quote(name)}
527
533
  SQL
528
534
 
529
- create_table_info = create_table_info(table_name)
530
-
531
535
  fk_info.map do |row|
532
536
  options = {
533
537
  column: row['column'],
@@ -535,14 +539,16 @@ module ActiveRecord
535
539
  primary_key: row['primary_key']
536
540
  }
537
541
 
538
- options[:on_update] = extract_foreign_key_action(create_table_info, row['name'], "UPDATE")
539
- options[:on_delete] = extract_foreign_key_action(create_table_info, row['name'], "DELETE")
542
+ options[:on_update] = extract_foreign_key_action(row['on_update'])
543
+ options[:on_delete] = extract_foreign_key_action(row['on_delete'])
540
544
 
541
545
  ForeignKeyDefinition.new(table_name, row['to_table'], options)
542
546
  end
543
547
  end
544
548
 
545
- def table_options(table_name)
549
+ def table_options(table_name) # :nodoc:
550
+ table_options = {}
551
+
546
552
  create_table_info = create_table_info(table_name)
547
553
 
548
554
  # strip create_definitions and partition_options
@@ -551,10 +557,14 @@ module ActiveRecord
551
557
  # strip AUTO_INCREMENT
552
558
  raw_table_options.sub!(/(ENGINE=\w+)(?: AUTO_INCREMENT=\d+)/, '\1')
553
559
 
560
+ table_options[:options] = raw_table_options
561
+
554
562
  # strip COMMENT
555
- raw_table_options.sub!(/ COMMENT='.+'/, '')
563
+ if raw_table_options.sub!(/ COMMENT='.+'/, '')
564
+ table_options[:comment] = table_comment(table_name)
565
+ end
556
566
 
557
- raw_table_options
567
+ table_options
558
568
  end
559
569
 
560
570
  # Maps logical Rails types to MySQL-specific data types.
@@ -682,7 +692,7 @@ module ActiveRecord
682
692
 
683
693
  def register_integer_type(mapping, key, options) # :nodoc:
684
694
  mapping.register_type(key) do |sql_type|
685
- if /\bunsigned\z/ === sql_type
695
+ if /\bunsigned\b/ === sql_type
686
696
  Type::UnsignedInteger.new(options)
687
697
  else
688
698
  Type::Integer.new(options)
@@ -702,29 +712,22 @@ module ActiveRecord
702
712
  MySQL::TypeMetadata.new(super(sql_type), extra: extra, strict: strict_mode?)
703
713
  end
704
714
 
705
- def add_index_length(option_strings, column_names, options = {})
706
- if options.is_a?(Hash) && length = options[:length]
715
+ def add_index_length(quoted_columns, **options)
716
+ if length = options[:length]
707
717
  case length
708
718
  when Hash
709
- column_names.each {|name| option_strings[name] += "(#{length[name]})" if length.has_key?(name) && length[name].present?}
719
+ quoted_columns.each { |name, column| column << "(#{length[name]})" if length[name].present? }
710
720
  when Integer
711
- column_names.each {|name| option_strings[name] += "(#{length})"}
721
+ quoted_columns.each { |name, column| column << "(#{length})" }
712
722
  end
713
723
  end
714
724
 
715
- return option_strings
725
+ quoted_columns
716
726
  end
717
727
 
718
- def quoted_columns_for_index(column_names, options = {})
719
- option_strings = Hash[column_names.map {|name| [name, '']}]
720
-
721
- # add index length
722
- option_strings = add_index_length(option_strings, column_names, options)
723
-
724
- # add index sort order
725
- option_strings = add_index_sort_order(option_strings, column_names, options)
726
-
727
- column_names.map {|name| quote_column_name(name) + option_strings[name]}
728
+ def add_options_for_index_columns(quoted_columns, **options)
729
+ quoted_columns = add_index_length(quoted_columns, options)
730
+ super
728
731
  end
729
732
 
730
733
  def translate_exception(exception, message)
@@ -883,21 +886,15 @@ module ActiveRecord
883
886
  end
884
887
  end
885
888
 
886
- def extract_foreign_key_action(structure, name, action) # :nodoc:
887
- if structure =~ /CONSTRAINT #{quote_column_name(name)} FOREIGN KEY .* REFERENCES .* ON #{action} (CASCADE|SET NULL|RESTRICT)/
888
- case $1
889
- when 'CASCADE'; :cascade
890
- when 'SET NULL'; :nullify
891
- end
889
+ def extract_foreign_key_action(specifier) # :nodoc:
890
+ case specifier
891
+ when 'CASCADE'; :cascade
892
+ when 'SET NULL'; :nullify
892
893
  end
893
894
  end
894
895
 
895
- def create_table_info_cache # :nodoc:
896
- @create_table_info_cache ||= {}
897
- end
898
-
899
896
  def create_table_info(table_name) # :nodoc:
900
- create_table_info_cache[table_name] ||= select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]
897
+ select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]
901
898
  end
902
899
 
903
900
  def create_table_definition(*args) # :nodoc: