activerecord 5.2.0.beta2 → 5.2.0.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 +5 -5
- data/CHANGELOG.md +231 -2
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_record.rb +1 -1
- data/lib/active_record/aggregations.rb +4 -5
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations.rb +18 -12
- data/lib/active_record/associations/alias_tracker.rb +2 -10
- data/lib/active_record/associations/association.rb +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +9 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -6
- data/lib/active_record/associations/builder/association.rb +2 -2
- data/lib/active_record/associations/builder/belongs_to.rb +7 -3
- data/lib/active_record/associations/collection_association.rb +2 -2
- data/lib/active_record/associations/collection_proxy.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +4 -17
- data/lib/active_record/associations/has_one_through_association.rb +5 -6
- data/lib/active_record/associations/preloader.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/through_association.rb +22 -9
- data/lib/active_record/attribute_methods.rb +1 -5
- data/lib/active_record/attribute_methods/dirty.rb +2 -4
- data/lib/active_record/attributes.rb +1 -1
- data/lib/active_record/autosave_association.rb +3 -0
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/collection_cache_key.rb +5 -6
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +57 -21
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +20 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +55 -15
- data/lib/active_record/connection_adapters/abstract_adapter.rb +19 -6
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +55 -64
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -1
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +0 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +21 -6
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +12 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +13 -4
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +170 -48
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +15 -5
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +63 -18
- data/lib/active_record/core.rb +12 -3
- data/lib/active_record/enum.rb +2 -0
- data/lib/active_record/fixtures.rb +28 -37
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +3 -4
- data/lib/active_record/log_subscriber.rb +41 -0
- data/lib/active_record/migration.rb +138 -120
- data/lib/active_record/migration/compatibility.rb +20 -0
- data/lib/active_record/model_schema.rb +19 -16
- data/lib/active_record/persistence.rb +8 -11
- data/lib/active_record/railtie.rb +7 -2
- data/lib/active_record/railties/databases.rake +8 -11
- data/lib/active_record/reflection.rb +10 -13
- data/lib/active_record/relation.rb +27 -17
- data/lib/active_record/relation/calculations.rb +17 -12
- data/lib/active_record/relation/finder_methods.rb +30 -37
- data/lib/active_record/relation/merger.rb +30 -2
- data/lib/active_record/relation/predicate_builder.rb +12 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +14 -24
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +16 -2
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/sanitization.rb +130 -128
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +12 -3
- data/lib/active_record/scoping/named.rb +6 -0
- data/lib/active_record/store.rb +1 -1
- data/lib/active_record/table_metadata.rb +10 -3
- data/lib/active_record/tasks/database_tasks.rb +4 -4
- data/lib/active_record/type_caster/map.rb +1 -1
- metadata +9 -9
@@ -6,7 +6,7 @@ module ActiveRecord
|
|
6
6
|
# this type are typically created and returned by methods in database
|
7
7
|
# adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes
|
8
8
|
class IndexDefinition # :nodoc:
|
9
|
-
attr_reader :table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using, :comment
|
9
|
+
attr_reader :table, :name, :unique, :columns, :lengths, :orders, :opclasses, :where, :type, :using, :comment
|
10
10
|
|
11
11
|
def initialize(
|
12
12
|
table, name,
|
@@ -14,6 +14,7 @@ module ActiveRecord
|
|
14
14
|
columns = [],
|
15
15
|
lengths: {},
|
16
16
|
orders: {},
|
17
|
+
opclasses: {},
|
17
18
|
where: nil,
|
18
19
|
type: nil,
|
19
20
|
using: nil,
|
@@ -23,13 +24,23 @@ module ActiveRecord
|
|
23
24
|
@name = name
|
24
25
|
@unique = unique
|
25
26
|
@columns = columns
|
26
|
-
@lengths = lengths
|
27
|
-
@orders = orders
|
27
|
+
@lengths = concise_options(lengths)
|
28
|
+
@orders = concise_options(orders)
|
29
|
+
@opclasses = concise_options(opclasses)
|
28
30
|
@where = where
|
29
31
|
@type = type
|
30
32
|
@using = using
|
31
33
|
@comment = comment
|
32
34
|
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def concise_options(options)
|
38
|
+
if columns.size == options.size && options.values.uniq.size == 1
|
39
|
+
options.values.first
|
40
|
+
else
|
41
|
+
options
|
42
|
+
end
|
43
|
+
end
|
33
44
|
end
|
34
45
|
|
35
46
|
# Abstract representation of a column definition. Instances of this type
|
@@ -85,6 +96,11 @@ module ActiveRecord
|
|
85
96
|
options[:primary_key] != default_primary_key
|
86
97
|
end
|
87
98
|
|
99
|
+
def validate?
|
100
|
+
options.fetch(:validate, true)
|
101
|
+
end
|
102
|
+
alias validated? validate?
|
103
|
+
|
88
104
|
def defined_for?(to_table_ord = nil, to_table: nil, **options)
|
89
105
|
if to_table_ord
|
90
106
|
self.to_table == to_table_ord.to_s
|
@@ -204,6 +220,7 @@ module ActiveRecord
|
|
204
220
|
:decimal,
|
205
221
|
:float,
|
206
222
|
:integer,
|
223
|
+
:json,
|
207
224
|
:string,
|
208
225
|
:text,
|
209
226
|
:time,
|
@@ -600,7 +600,7 @@ module ActiveRecord
|
|
600
600
|
# to provide these in a migration's +change+ method so it can be reverted.
|
601
601
|
# In that case, +type+ and +options+ will be used by #add_column.
|
602
602
|
def remove_column(table_name, column_name, type = nil, options = {})
|
603
|
-
execute "ALTER TABLE #{quote_table_name(table_name)}
|
603
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, options)}"
|
604
604
|
end
|
605
605
|
|
606
606
|
# Changes the column's definition according to the new options.
|
@@ -715,7 +715,7 @@ module ActiveRecord
|
|
715
715
|
#
|
716
716
|
# CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
|
717
717
|
#
|
718
|
-
# Note: MySQL
|
718
|
+
# Note: MySQL only supports index order from 8.0.1 onwards (earlier versions accepted the syntax but ignored it).
|
719
719
|
#
|
720
720
|
# ====== Creating a partial index
|
721
721
|
#
|
@@ -738,6 +738,28 @@ module ActiveRecord
|
|
738
738
|
#
|
739
739
|
# Note: only supported by PostgreSQL and MySQL
|
740
740
|
#
|
741
|
+
# ====== Creating an index with a specific operator class
|
742
|
+
#
|
743
|
+
# add_index(:developers, :name, using: 'gist', opclass: :gist_trgm_ops)
|
744
|
+
#
|
745
|
+
# generates:
|
746
|
+
#
|
747
|
+
# CREATE INDEX developers_on_name ON developers USING gist (name gist_trgm_ops) -- PostgreSQL
|
748
|
+
#
|
749
|
+
# add_index(:developers, [:name, :city], using: 'gist', opclass: { city: :gist_trgm_ops })
|
750
|
+
#
|
751
|
+
# generates:
|
752
|
+
#
|
753
|
+
# CREATE INDEX developers_on_name_and_city ON developers USING gist (name, city gist_trgm_ops) -- PostgreSQL
|
754
|
+
#
|
755
|
+
# add_index(:developers, [:name, :city], using: 'gist', opclass: :gist_trgm_ops)
|
756
|
+
#
|
757
|
+
# generates:
|
758
|
+
#
|
759
|
+
# CREATE INDEX developers_on_name_and_city ON developers USING gist (name gist_trgm_ops, city gist_trgm_ops) -- PostgreSQL
|
760
|
+
#
|
761
|
+
# Note: only supported by PostgreSQL
|
762
|
+
#
|
741
763
|
# ====== Creating an index with a specific type
|
742
764
|
#
|
743
765
|
# add_index(:developers, :name, type: :fulltext)
|
@@ -942,6 +964,8 @@ module ActiveRecord
|
|
942
964
|
# Action that happens <tt>ON DELETE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
|
943
965
|
# [<tt>:on_update</tt>]
|
944
966
|
# Action that happens <tt>ON UPDATE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
|
967
|
+
# [<tt>:validate</tt>]
|
968
|
+
# (Postgres only) Specify whether or not the constraint should be validated. Defaults to +true+.
|
945
969
|
def add_foreign_key(from_table, to_table, options = {})
|
946
970
|
return unless supports_foreign_keys?
|
947
971
|
|
@@ -1025,8 +1049,8 @@ module ActiveRecord
|
|
1025
1049
|
sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
|
1026
1050
|
|
1027
1051
|
migrated = ActiveRecord::SchemaMigration.all_versions.map(&:to_i)
|
1028
|
-
versions =
|
1029
|
-
|
1052
|
+
versions = migration_context.migration_files.map do |file|
|
1053
|
+
migration_context.parse_migration_filename(file).first.to_i
|
1030
1054
|
end
|
1031
1055
|
|
1032
1056
|
unless migrated.include?(version)
|
@@ -1120,7 +1144,7 @@ module ActiveRecord
|
|
1120
1144
|
def add_index_options(table_name, column_name, comment: nil, **options) # :nodoc:
|
1121
1145
|
column_names = index_column_names(column_name)
|
1122
1146
|
|
1123
|
-
options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type)
|
1147
|
+
options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type, :opclass)
|
1124
1148
|
|
1125
1149
|
index_type = options[:type].to_s if options.key?(:type)
|
1126
1150
|
index_type ||= options[:unique] ? "UNIQUE" : ""
|
@@ -1173,20 +1197,22 @@ module ActiveRecord
|
|
1173
1197
|
end
|
1174
1198
|
|
1175
1199
|
def add_index_sort_order(quoted_columns, **options)
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
order = order.symbolize_keys
|
1180
|
-
quoted_columns.each { |name, column| column << " #{order[name].upcase}" if order[name].present? }
|
1181
|
-
when String
|
1182
|
-
quoted_columns.each { |name, column| column << " #{order.upcase}" if order.present? }
|
1183
|
-
end
|
1200
|
+
orders = options_for_index_columns(options[:order])
|
1201
|
+
quoted_columns.each do |name, column|
|
1202
|
+
column << " #{orders[name].upcase}" if orders[name].present?
|
1184
1203
|
end
|
1204
|
+
end
|
1185
1205
|
|
1186
|
-
|
1206
|
+
def options_for_index_columns(options)
|
1207
|
+
if options.is_a?(Hash)
|
1208
|
+
options.symbolize_keys
|
1209
|
+
else
|
1210
|
+
Hash.new { |hash, column| hash[column] = options }
|
1211
|
+
end
|
1187
1212
|
end
|
1188
1213
|
|
1189
|
-
# Overridden by the MySQL adapter for supporting index lengths
|
1214
|
+
# Overridden by the MySQL adapter for supporting index lengths and by
|
1215
|
+
# the PostgreSQL adapter for supporting operator classes.
|
1190
1216
|
def add_options_for_index_columns(quoted_columns, **options)
|
1191
1217
|
if supports_index_sort_order?
|
1192
1218
|
quoted_columns = add_index_sort_order(quoted_columns, options)
|
@@ -1340,6 +1366,20 @@ module ActiveRecord
|
|
1340
1366
|
options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
|
1341
1367
|
end
|
1342
1368
|
|
1369
|
+
def add_column_for_alter(table_name, column_name, type, options = {})
|
1370
|
+
td = create_table_definition(table_name)
|
1371
|
+
cd = td.new_column_definition(column_name, type, options)
|
1372
|
+
schema_creation.accept(AddColumnDefinition.new(cd))
|
1373
|
+
end
|
1374
|
+
|
1375
|
+
def remove_column_for_alter(table_name, column_name, type = nil, options = {})
|
1376
|
+
"DROP COLUMN #{quote_column_name(column_name)}"
|
1377
|
+
end
|
1378
|
+
|
1379
|
+
def remove_columns_for_alter(table_name, *column_names)
|
1380
|
+
column_names.map { |column_name| remove_column_for_alter(table_name, column_name) }
|
1381
|
+
end
|
1382
|
+
|
1343
1383
|
def insert_versions_sql(versions)
|
1344
1384
|
sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
|
1345
1385
|
|
@@ -119,6 +119,14 @@ module ActiveRecord
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
+
def migrations_paths
|
123
|
+
@config[:migrations_paths] || Migrator.migrations_paths
|
124
|
+
end
|
125
|
+
|
126
|
+
def migration_context
|
127
|
+
MigrationContext.new(migrations_paths)
|
128
|
+
end
|
129
|
+
|
122
130
|
class Version
|
123
131
|
include Comparable
|
124
132
|
|
@@ -272,6 +280,11 @@ module ActiveRecord
|
|
272
280
|
false
|
273
281
|
end
|
274
282
|
|
283
|
+
# Does this adapter support creating invalid constraints?
|
284
|
+
def supports_validate_constraints?
|
285
|
+
false
|
286
|
+
end
|
287
|
+
|
275
288
|
# Does this adapter support creating foreign key constraints
|
276
289
|
# in the same statement as creating the table?
|
277
290
|
def supports_foreign_keys_in_create?
|
@@ -313,6 +326,11 @@ module ActiveRecord
|
|
313
326
|
false
|
314
327
|
end
|
315
328
|
|
329
|
+
# Does this adapter support foreign/external tables?
|
330
|
+
def supports_foreign_tables?
|
331
|
+
false
|
332
|
+
end
|
333
|
+
|
316
334
|
# This is meant to be implemented by the adapters that support extensions
|
317
335
|
def disable_extension(name)
|
318
336
|
end
|
@@ -532,12 +550,7 @@ module ActiveRecord
|
|
532
550
|
end
|
533
551
|
|
534
552
|
def extract_limit(sql_type)
|
535
|
-
|
536
|
-
when /^bigint/i
|
537
|
-
8
|
538
|
-
when /\((.*)\)/
|
539
|
-
$1.to_i
|
540
|
-
end
|
553
|
+
$1.to_i if sql_type =~ /\((.*)\)/
|
541
554
|
end
|
542
555
|
|
543
556
|
def translate_exception_class(e, sql)
|
@@ -117,11 +117,11 @@ module ActiveRecord
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def get_advisory_lock(lock_name, timeout = 0) # :nodoc:
|
120
|
-
query_value("SELECT GET_LOCK(#{quote(lock_name)}, #{timeout})") == 1
|
120
|
+
query_value("SELECT GET_LOCK(#{quote(lock_name.to_s)}, #{timeout})") == 1
|
121
121
|
end
|
122
122
|
|
123
123
|
def release_advisory_lock(lock_name) # :nodoc:
|
124
|
-
query_value("SELECT RELEASE_LOCK(#{quote(lock_name)})") == 1
|
124
|
+
query_value("SELECT RELEASE_LOCK(#{quote(lock_name.to_s)})") == 1
|
125
125
|
end
|
126
126
|
|
127
127
|
def native_database_types
|
@@ -249,7 +249,7 @@ module ActiveRecord
|
|
249
249
|
# create_database 'matt_development', charset: :big5
|
250
250
|
def create_database(name, options = {})
|
251
251
|
if options[:collation]
|
252
|
-
execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT
|
252
|
+
execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT COLLATE #{quote_table_name(options[:collation])}"
|
253
253
|
else
|
254
254
|
execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT CHARACTER SET #{quote_table_name(options[:charset] || 'utf8')}"
|
255
255
|
end
|
@@ -292,14 +292,10 @@ module ActiveRecord
|
|
292
292
|
SQL
|
293
293
|
end
|
294
294
|
|
295
|
-
def create_table(table_name, **options) #:nodoc:
|
296
|
-
super(table_name, options: "ENGINE=InnoDB", **options)
|
297
|
-
end
|
298
|
-
|
299
295
|
def bulk_change_table(table_name, operations) #:nodoc:
|
300
296
|
sqls = operations.flat_map do |command, args|
|
301
297
|
table, arguments = args.shift, args
|
302
|
-
method = :"#{command}
|
298
|
+
method = :"#{command}_for_alter"
|
303
299
|
|
304
300
|
if respond_to?(method, true)
|
305
301
|
send(method, table, *arguments)
|
@@ -372,11 +368,11 @@ module ActiveRecord
|
|
372
368
|
end
|
373
369
|
|
374
370
|
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
375
|
-
execute("ALTER TABLE #{quote_table_name(table_name)} #{
|
371
|
+
execute("ALTER TABLE #{quote_table_name(table_name)} #{change_column_for_alter(table_name, column_name, type, options)}")
|
376
372
|
end
|
377
373
|
|
378
374
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
379
|
-
execute("ALTER TABLE #{quote_table_name(table_name)} #{
|
375
|
+
execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_for_alter(table_name, column_name, new_column_name)}")
|
380
376
|
rename_column_indexes(table_name, column_name, new_column_name)
|
381
377
|
end
|
382
378
|
|
@@ -403,12 +399,13 @@ module ActiveRecord
|
|
403
399
|
fk.constraint_name AS 'name',
|
404
400
|
rc.update_rule AS 'on_update',
|
405
401
|
rc.delete_rule AS 'on_delete'
|
406
|
-
FROM information_schema.
|
407
|
-
JOIN information_schema.
|
402
|
+
FROM information_schema.referential_constraints rc
|
403
|
+
JOIN information_schema.key_column_usage fk
|
408
404
|
USING (constraint_schema, constraint_name)
|
409
405
|
WHERE fk.referenced_column_name IS NOT NULL
|
410
406
|
AND fk.table_schema = #{scope[:schema]}
|
411
407
|
AND fk.table_name = #{scope[:name]}
|
408
|
+
AND rc.constraint_schema = #{scope[:schema]}
|
412
409
|
AND rc.table_name = #{scope[:name]}
|
413
410
|
SQL
|
414
411
|
|
@@ -529,23 +526,49 @@ module ActiveRecord
|
|
529
526
|
index.using == :btree || super
|
530
527
|
end
|
531
528
|
|
532
|
-
def
|
533
|
-
|
529
|
+
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
530
|
+
with_multi_statements do
|
531
|
+
super { discard_remaining_results }
|
532
|
+
end
|
534
533
|
end
|
535
534
|
|
536
535
|
private
|
536
|
+
def combine_multi_statements(total_sql)
|
537
|
+
total_sql.each_with_object([]) do |sql, total_sql_chunks|
|
538
|
+
previous_packet = total_sql_chunks.last
|
539
|
+
sql << ";\n"
|
540
|
+
if max_allowed_packet_reached?(sql, previous_packet) || total_sql_chunks.empty?
|
541
|
+
total_sql_chunks << sql
|
542
|
+
else
|
543
|
+
previous_packet << sql
|
544
|
+
end
|
545
|
+
end
|
546
|
+
end
|
537
547
|
|
538
|
-
def
|
539
|
-
|
540
|
-
|
541
|
-
|
548
|
+
def max_allowed_packet_reached?(current_packet, previous_packet)
|
549
|
+
if current_packet.bytesize > max_allowed_packet
|
550
|
+
raise ActiveRecordError, "Fixtures set is too large #{current_packet.bytesize}. Consider increasing the max_allowed_packet variable."
|
551
|
+
elsif previous_packet.nil?
|
552
|
+
false
|
553
|
+
else
|
554
|
+
(current_packet.bytesize + previous_packet.bytesize) > max_allowed_packet
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
def max_allowed_packet
|
559
|
+
bytes_margin = 2
|
560
|
+
@max_allowed_packet ||= (show_variable("max_allowed_packet") - bytes_margin)
|
561
|
+
end
|
562
|
+
|
563
|
+
def with_multi_statements
|
564
|
+
previous_flags = @config[:flags]
|
565
|
+
@config[:flags] = Mysql2::Client::MULTI_STATEMENTS
|
566
|
+
reconnect!
|
542
567
|
|
543
|
-
sql_mode = "REPLACE(@@sql_mode, '#{mode}', '')"
|
544
|
-
execute("SET @@SESSION.sql_mode = #{sql_mode}")
|
545
568
|
yield
|
546
569
|
ensure
|
547
|
-
|
548
|
-
|
570
|
+
@config[:flags] = previous_flags
|
571
|
+
reconnect!
|
549
572
|
end
|
550
573
|
|
551
574
|
def initialize_type_map(m = type_map)
|
@@ -605,25 +628,6 @@ module ActiveRecord
|
|
605
628
|
end
|
606
629
|
end
|
607
630
|
|
608
|
-
def add_index_length(quoted_columns, **options)
|
609
|
-
if length = options[:length]
|
610
|
-
case length
|
611
|
-
when Hash
|
612
|
-
length = length.symbolize_keys
|
613
|
-
quoted_columns.each { |name, column| column << "(#{length[name]})" if length[name].present? }
|
614
|
-
when Integer
|
615
|
-
quoted_columns.each { |name, column| column << "(#{length})" }
|
616
|
-
end
|
617
|
-
end
|
618
|
-
|
619
|
-
quoted_columns
|
620
|
-
end
|
621
|
-
|
622
|
-
def add_options_for_index_columns(quoted_columns, **options)
|
623
|
-
quoted_columns = add_index_length(quoted_columns, options)
|
624
|
-
super
|
625
|
-
end
|
626
|
-
|
627
631
|
# See https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html
|
628
632
|
ER_DUP_ENTRY = 1062
|
629
633
|
ER_NOT_NULL_VIOLATION = 1048
|
@@ -671,13 +675,7 @@ module ActiveRecord
|
|
671
675
|
end
|
672
676
|
end
|
673
677
|
|
674
|
-
def
|
675
|
-
td = create_table_definition(table_name)
|
676
|
-
cd = td.new_column_definition(column_name, type, options)
|
677
|
-
schema_creation.accept(AddColumnDefinition.new(cd))
|
678
|
-
end
|
679
|
-
|
680
|
-
def change_column_sql(table_name, column_name, type, options = {})
|
678
|
+
def change_column_for_alter(table_name, column_name, type, options = {})
|
681
679
|
column = column_for(table_name, column_name)
|
682
680
|
type ||= column.sql_type
|
683
681
|
|
@@ -698,7 +696,7 @@ module ActiveRecord
|
|
698
696
|
schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
|
699
697
|
end
|
700
698
|
|
701
|
-
def
|
699
|
+
def rename_column_for_alter(table_name, column_name, new_column_name)
|
702
700
|
column = column_for(table_name, column_name)
|
703
701
|
options = {
|
704
702
|
default: column.default,
|
@@ -712,31 +710,23 @@ module ActiveRecord
|
|
712
710
|
schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
|
713
711
|
end
|
714
712
|
|
715
|
-
def
|
716
|
-
"DROP #{quote_column_name(column_name)}"
|
717
|
-
end
|
718
|
-
|
719
|
-
def remove_columns_sql(table_name, *column_names)
|
720
|
-
column_names.map { |column_name| remove_column_sql(table_name, column_name) }
|
721
|
-
end
|
722
|
-
|
723
|
-
def add_index_sql(table_name, column_name, options = {})
|
713
|
+
def add_index_for_alter(table_name, column_name, options = {})
|
724
714
|
index_name, index_type, index_columns, _, index_algorithm, index_using = add_index_options(table_name, column_name, options)
|
725
715
|
index_algorithm[0, 0] = ", " if index_algorithm.present?
|
726
716
|
"ADD #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_algorithm}"
|
727
717
|
end
|
728
718
|
|
729
|
-
def
|
719
|
+
def remove_index_for_alter(table_name, options = {})
|
730
720
|
index_name = index_name_for_remove(table_name, options)
|
731
721
|
"DROP INDEX #{quote_column_name(index_name)}"
|
732
722
|
end
|
733
723
|
|
734
|
-
def
|
735
|
-
[
|
724
|
+
def add_timestamps_for_alter(table_name, options = {})
|
725
|
+
[add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
|
736
726
|
end
|
737
727
|
|
738
|
-
def
|
739
|
-
[
|
728
|
+
def remove_timestamps_for_alter(table_name, options = {})
|
729
|
+
[remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
|
740
730
|
end
|
741
731
|
|
742
732
|
# MySQL is too stupid to create a temporary table for use subquery, so we have
|
@@ -749,7 +739,8 @@ module ActiveRecord
|
|
749
739
|
# to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on'
|
750
740
|
subselect.distinct unless select.limit || select.offset || select.orders.any?
|
751
741
|
|
752
|
-
|
742
|
+
key_name = quote_column_name(key.name)
|
743
|
+
Arel::SelectManager.new(subselect.as("__active_record_temp")).project(Arel.sql(key_name))
|
753
744
|
end
|
754
745
|
|
755
746
|
def supports_rename_index?
|