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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +196 -2
- data/README.rdoc +1 -1
- data/lib/active_record.rb +1 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/association_relation.rb +4 -1
- data/lib/active_record/associations.rb +5 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +4 -2
- data/lib/active_record/associations/builder/singular_association.rb +10 -1
- data/lib/active_record/associations/collection_association.rb +22 -17
- data/lib/active_record/associations/collection_proxy.rb +20 -7
- data/lib/active_record/associations/has_many_through_association.rb +4 -0
- data/lib/active_record/associations/join_dependency.rb +10 -4
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader/association.rb +18 -4
- data/lib/active_record/associations/preloader/collection_association.rb +0 -1
- data/lib/active_record/associations/preloader/singular_association.rb +0 -1
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/attribute.rb +3 -3
- data/lib/active_record/attribute_methods.rb +3 -7
- data/lib/active_record/attribute_methods/primary_key.rb +14 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_set.rb +2 -0
- data/lib/active_record/attribute_set/builder.rb +29 -7
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +15 -11
- data/lib/active_record/base.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +40 -32
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +29 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +8 -7
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +37 -33
- data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -5
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +42 -45
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +6 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -5
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +12 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +7 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +6 -2
- data/lib/active_record/core.rb +3 -1
- data/lib/active_record/enum.rb +6 -5
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/integration.rb +13 -10
- data/lib/active_record/migration.rb +6 -5
- data/lib/active_record/model_schema.rb +134 -47
- data/lib/active_record/no_touching.rb +4 -0
- data/lib/active_record/persistence.rb +10 -4
- data/lib/active_record/query_cache.rb +13 -15
- data/lib/active_record/querying.rb +3 -3
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/reflection.rb +8 -0
- data/lib/active_record/relation.rb +7 -4
- data/lib/active_record/relation/calculations.rb +11 -11
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +11 -9
- data/lib/active_record/relation/query_methods.rb +3 -3
- data/lib/active_record/result.rb +7 -1
- data/lib/active_record/sanitization.rb +11 -1
- data/lib/active_record/schema_dumper.rb +10 -17
- data/lib/active_record/scoping/named.rb +1 -1
- data/lib/active_record/statement_cache.rb +2 -2
- data/lib/active_record/table_metadata.rb +4 -3
- data/lib/active_record/touch_later.rb +6 -1
- data/lib/active_record/type/internal/abstract_json.rb +5 -1
- data/lib/active_record/validations/uniqueness.rb +3 -4
- 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?(
|
55
|
-
if
|
56
|
-
|
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 ==
|
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
|
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
|
-
|
133
|
-
|
134
|
-
|
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.
|
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
|
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,
|
851
|
-
if
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
1167
|
-
|
1167
|
+
|
1168
|
+
def add_index_sort_order(quoted_columns, **options)
|
1169
|
+
if order = options[:order]
|
1168
1170
|
case order
|
1169
1171
|
when Hash
|
1170
|
-
|
1172
|
+
quoted_columns.each { |name, column| column << " #{order[name].upcase}" if order[name].present? }
|
1171
1173
|
when String
|
1172
|
-
|
1174
|
+
quoted_columns.each { |name, column| column << " #{order.upcase}" if order.present? }
|
1173
1175
|
end
|
1174
1176
|
end
|
1175
1177
|
|
1176
|
-
|
1178
|
+
quoted_columns
|
1177
1179
|
end
|
1178
1180
|
|
1179
1181
|
# Overridden by the MySQL adapter for supporting index lengths
|
1180
|
-
def
|
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
|
-
|
1184
|
+
quoted_columns = add_index_sort_order(quoted_columns, options)
|
1188
1185
|
end
|
1189
1186
|
|
1190
|
-
|
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 =
|
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
|
-
|
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, [],
|
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
|
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
|
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
|
519
|
-
SELECT fk.referenced_table_name
|
520
|
-
|
521
|
-
|
522
|
-
|
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
|
-
|
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(
|
539
|
-
options[:on_delete] = extract_foreign_key_action(
|
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
|
-
|
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\
|
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(
|
706
|
-
if
|
715
|
+
def add_index_length(quoted_columns, **options)
|
716
|
+
if length = options[:length]
|
707
717
|
case length
|
708
718
|
when Hash
|
709
|
-
|
719
|
+
quoted_columns.each { |name, column| column << "(#{length[name]})" if length[name].present? }
|
710
720
|
when Integer
|
711
|
-
|
721
|
+
quoted_columns.each { |name, column| column << "(#{length})" }
|
712
722
|
end
|
713
723
|
end
|
714
724
|
|
715
|
-
|
725
|
+
quoted_columns
|
716
726
|
end
|
717
727
|
|
718
|
-
def
|
719
|
-
|
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(
|
887
|
-
|
888
|
-
|
889
|
-
|
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
|
-
|
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:
|