activerecord 6.0.0.beta1 → 6.0.0.beta2
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 +99 -2
- data/lib/active_record.rb +7 -0
- data/lib/active_record/associations/association.rb +17 -0
- data/lib/active_record/associations/collection_association.rb +5 -6
- data/lib/active_record/associations/collection_proxy.rb +12 -41
- data/lib/active_record/associations/has_many_association.rb +1 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -6
- data/lib/active_record/associations/preloader/association.rb +3 -4
- data/lib/active_record/associations/preloader/through_association.rb +9 -20
- data/lib/active_record/callbacks.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +25 -12
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +17 -9
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +5 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +47 -33
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +16 -8
- data/lib/active_record/connection_adapters/abstract/transaction.rb +5 -2
- data/lib/active_record/connection_adapters/abstract_adapter.rb +6 -4
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +28 -65
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +59 -1
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +6 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +98 -89
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -27
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +30 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +27 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +8 -5
- data/lib/active_record/connection_handling.rb +9 -4
- data/lib/active_record/core.rb +13 -1
- data/lib/active_record/database_configurations.rb +30 -10
- data/lib/active_record/database_configurations/hash_config.rb +1 -1
- data/lib/active_record/database_configurations/url_config.rb +9 -4
- data/lib/active_record/errors.rb +17 -12
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +90 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/migration/compatibility.rb +62 -63
- data/lib/active_record/persistence.rb +6 -6
- data/lib/active_record/querying.rb +2 -3
- data/lib/active_record/railtie.rb +9 -0
- data/lib/active_record/railties/collection_cache_association_loading.rb +3 -3
- data/lib/active_record/reflection.rb +15 -29
- data/lib/active_record/relation.rb +86 -15
- data/lib/active_record/relation/calculations.rb +2 -4
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +8 -4
- data/lib/active_record/relation/query_attribute.rb +5 -3
- data/lib/active_record/relation/query_methods.rb +28 -8
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +1 -5
- data/lib/active_record/scoping.rb +6 -7
- data/lib/active_record/scoping/default.rb +1 -8
- data/lib/active_record/scoping/named.rb +9 -1
- data/lib/active_record/test_fixtures.rb +2 -2
- data/lib/active_record/timestamp.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +3 -1
- data/lib/arel.rb +7 -0
- data/lib/arel/nodes/and.rb +1 -1
- data/lib/arel/nodes/case.rb +1 -1
- metadata +11 -8
@@ -77,9 +77,6 @@ module ActiveRecord
|
|
77
77
|
|
78
78
|
SIMPLE_INT = /\A\d+\z/
|
79
79
|
|
80
|
-
attr_writer :visitor
|
81
|
-
deprecate :visitor=
|
82
|
-
|
83
80
|
attr_accessor :pool
|
84
81
|
attr_reader :schema_cache, :visitor, :owner, :logger, :lock, :prepared_statements, :prevent_writes
|
85
82
|
alias :in_use? :owner
|
@@ -105,7 +102,7 @@ module ActiveRecord
|
|
105
102
|
end
|
106
103
|
|
107
104
|
def self.build_read_query_regexp(*parts) # :nodoc:
|
108
|
-
parts = parts.map { |part| /\A\s*#{part}/i }
|
105
|
+
parts = parts.map { |part| /\A[\(\s]*#{part}/i }
|
109
106
|
Regexp.union(*parts)
|
110
107
|
end
|
111
108
|
|
@@ -338,6 +335,7 @@ module ActiveRecord
|
|
338
335
|
def supports_foreign_keys_in_create?
|
339
336
|
supports_foreign_keys?
|
340
337
|
end
|
338
|
+
deprecate :supports_foreign_keys_in_create?
|
341
339
|
|
342
340
|
# Does this adapter support views?
|
343
341
|
def supports_views?
|
@@ -508,6 +506,10 @@ module ActiveRecord
|
|
508
506
|
@connection
|
509
507
|
end
|
510
508
|
|
509
|
+
def default_uniqueness_comparison(attribute, value) # :nodoc:
|
510
|
+
case_sensitive_comparison(attribute, value)
|
511
|
+
end
|
512
|
+
|
511
513
|
def case_sensitive_comparison(attribute, value) # :nodoc:
|
512
514
|
attribute.eq(value)
|
513
515
|
end
|
@@ -29,7 +29,7 @@ module ActiveRecord
|
|
29
29
|
NATIVE_DATABASE_TYPES = {
|
30
30
|
primary_key: "bigint auto_increment PRIMARY KEY",
|
31
31
|
string: { name: "varchar", limit: 255 },
|
32
|
-
text: { name: "text"
|
32
|
+
text: { name: "text" },
|
33
33
|
integer: { name: "int", limit: 4 },
|
34
34
|
float: { name: "float", limit: 24 },
|
35
35
|
decimal: { name: "decimal" },
|
@@ -37,7 +37,8 @@ module ActiveRecord
|
|
37
37
|
timestamp: { name: "timestamp" },
|
38
38
|
time: { name: "time" },
|
39
39
|
date: { name: "date" },
|
40
|
-
binary: { name: "blob"
|
40
|
+
binary: { name: "blob" },
|
41
|
+
blob: { name: "blob" },
|
41
42
|
boolean: { name: "tinyint", limit: 1 },
|
42
43
|
json: { name: "json" },
|
43
44
|
}
|
@@ -165,9 +166,9 @@ module ActiveRecord
|
|
165
166
|
|
166
167
|
def explain(arel, binds = [])
|
167
168
|
sql = "EXPLAIN #{to_sql(arel, binds)}"
|
168
|
-
start =
|
169
|
+
start = Concurrent.monotonic_time
|
169
170
|
result = exec_query(sql, "EXPLAIN", binds)
|
170
|
-
elapsed =
|
171
|
+
elapsed = Concurrent.monotonic_time - start
|
171
172
|
|
172
173
|
MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
|
173
174
|
end
|
@@ -430,30 +431,6 @@ module ActiveRecord
|
|
430
431
|
table_options
|
431
432
|
end
|
432
433
|
|
433
|
-
# Maps logical Rails types to MySQL-specific data types.
|
434
|
-
def type_to_sql(type, limit: nil, precision: nil, scale: nil, unsigned: nil, **) # :nodoc:
|
435
|
-
sql = \
|
436
|
-
case type.to_s
|
437
|
-
when "integer"
|
438
|
-
integer_to_sql(limit)
|
439
|
-
when "text"
|
440
|
-
text_to_sql(limit)
|
441
|
-
when "blob"
|
442
|
-
binary_to_sql(limit)
|
443
|
-
when "binary"
|
444
|
-
if (0..0xfff) === limit
|
445
|
-
"varbinary(#{limit})"
|
446
|
-
else
|
447
|
-
binary_to_sql(limit)
|
448
|
-
end
|
449
|
-
else
|
450
|
-
super
|
451
|
-
end
|
452
|
-
|
453
|
-
sql = "#{sql} unsigned" if unsigned && type != :primary_key
|
454
|
-
sql
|
455
|
-
end
|
456
|
-
|
457
434
|
# SHOW VARIABLES LIKE 'name'
|
458
435
|
def show_variable(name)
|
459
436
|
query_value("SELECT @@#{name}", "SCHEMA")
|
@@ -627,6 +604,7 @@ module ActiveRecord
|
|
627
604
|
ER_LOCK_WAIT_TIMEOUT = 1205
|
628
605
|
ER_QUERY_INTERRUPTED = 1317
|
629
606
|
ER_QUERY_TIMEOUT = 3024
|
607
|
+
ER_FK_INCOMPATIBLE_COLUMNS = 3780
|
630
608
|
|
631
609
|
def translate_exception(exception, message:, sql:, binds:)
|
632
610
|
case error_number(exception)
|
@@ -634,7 +612,7 @@ module ActiveRecord
|
|
634
612
|
RecordNotUnique.new(message, sql: sql, binds: binds)
|
635
613
|
when ER_NO_REFERENCED_ROW, ER_ROW_IS_REFERENCED, ER_ROW_IS_REFERENCED_2, ER_NO_REFERENCED_ROW_2
|
636
614
|
InvalidForeignKey.new(message, sql: sql, binds: binds)
|
637
|
-
when ER_CANNOT_ADD_FOREIGN
|
615
|
+
when ER_CANNOT_ADD_FOREIGN, ER_FK_INCOMPATIBLE_COLUMNS
|
638
616
|
mismatched_foreign_key(message, sql: sql, binds: binds)
|
639
617
|
when ER_CANNOT_CREATE_TABLE
|
640
618
|
if message.include?("errno: 150")
|
@@ -708,6 +686,12 @@ module ActiveRecord
|
|
708
686
|
end
|
709
687
|
|
710
688
|
def add_timestamps_for_alter(table_name, options = {})
|
689
|
+
options[:null] = false if options[:null].nil?
|
690
|
+
|
691
|
+
if !options.key?(:precision) && supports_datetime_with_precision?
|
692
|
+
options[:precision] = 6
|
693
|
+
end
|
694
|
+
|
711
695
|
[add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
|
712
696
|
end
|
713
697
|
|
@@ -787,48 +771,27 @@ module ActiveRecord
|
|
787
771
|
end
|
788
772
|
|
789
773
|
def mismatched_foreign_key(message, sql:, binds:)
|
790
|
-
|
791
|
-
|
792
|
-
|
774
|
+
match = %r/
|
775
|
+
(?:CREATE|ALTER)\s+TABLE\s*(?:`?\w+`?\.)?`?(?<table>\w+)`?.+?
|
776
|
+
FOREIGN\s+KEY\s*\(`?(?<foreign_key>\w+)`?\)\s*
|
777
|
+
REFERENCES\s*(`?(?<target_table>\w+)`?)\s*\(`?(?<primary_key>\w+)`?\)
|
778
|
+
/xmi.match(sql)
|
779
|
+
|
780
|
+
options = {
|
793
781
|
message: message,
|
794
782
|
sql: sql,
|
795
783
|
binds: binds,
|
796
|
-
|
797
|
-
foreign_key: parts[1],
|
798
|
-
target_table: parts[2],
|
799
|
-
primary_key: parts[3],
|
800
|
-
)
|
801
|
-
end
|
802
|
-
|
803
|
-
def integer_to_sql(limit) # :nodoc:
|
804
|
-
case limit
|
805
|
-
when 1; "tinyint"
|
806
|
-
when 2; "smallint"
|
807
|
-
when 3; "mediumint"
|
808
|
-
when nil, 4; "int"
|
809
|
-
when 5..8; "bigint"
|
810
|
-
else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a decimal with scale 0 instead.")
|
811
|
-
end
|
812
|
-
end
|
784
|
+
}
|
813
785
|
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
else raise(ActiveRecordError, "No text type has byte length #{limit}")
|
786
|
+
if match
|
787
|
+
options[:table] = match[:table]
|
788
|
+
options[:foreign_key] = match[:foreign_key]
|
789
|
+
options[:target_table] = match[:target_table]
|
790
|
+
options[:primary_key] = match[:primary_key]
|
791
|
+
options[:primary_key_column] = column_for(match[:target_table], match[:primary_key])
|
821
792
|
end
|
822
|
-
end
|
823
793
|
|
824
|
-
|
825
|
-
case limit
|
826
|
-
when 0..0xff; "tinyblob"
|
827
|
-
when nil, 0x100..0xffff; "blob"
|
828
|
-
when 0x10000..0xffffff; "mediumblob"
|
829
|
-
when 0x1000000..0xffffffff; "longblob"
|
830
|
-
else raise(ActiveRecordError, "No binary type has byte length #{limit}")
|
831
|
-
end
|
794
|
+
MismatchedForeignKey.new(options)
|
832
795
|
end
|
833
796
|
|
834
797
|
def version_string
|
@@ -4,48 +4,56 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module MySQL
|
6
6
|
module ColumnMethods
|
7
|
-
|
8
|
-
args.each { |name| column(name, :blob, options) }
|
9
|
-
end
|
7
|
+
extend ActiveSupport::Concern
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
##
|
10
|
+
# :method: blob
|
11
|
+
# :call-seq: blob(*names, **options)
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
##
|
14
|
+
# :method: tinyblob
|
15
|
+
# :call-seq: tinyblob(*names, **options)
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
##
|
18
|
+
# :method: mediumblob
|
19
|
+
# :call-seq: mediumblob(*names, **options)
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
##
|
22
|
+
# :method: longblob
|
23
|
+
# :call-seq: longblob(*names, **options)
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
##
|
26
|
+
# :method: tinytext
|
27
|
+
# :call-seq: tinytext(*names, **options)
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
##
|
30
|
+
# :method: mediumtext
|
31
|
+
# :call-seq: mediumtext(*names, **options)
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
##
|
34
|
+
# :method: longtext
|
35
|
+
# :call-seq: longtext(*names, **options)
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
##
|
38
|
+
# :method: unsigned_integer
|
39
|
+
# :call-seq: unsigned_integer(*names, **options)
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
##
|
42
|
+
# :method: unsigned_bigint
|
43
|
+
# :call-seq: unsigned_bigint(*names, **options)
|
44
|
+
|
45
|
+
##
|
46
|
+
# :method: unsigned_float
|
47
|
+
# :call-seq: unsigned_float(*names, **options)
|
48
|
+
|
49
|
+
##
|
50
|
+
# :method: unsigned_decimal
|
51
|
+
# :call-seq: unsigned_decimal(*names, **options)
|
46
52
|
|
47
|
-
|
48
|
-
|
53
|
+
included do
|
54
|
+
define_column_methods :blob, :tinyblob, :mediumblob, :longblob,
|
55
|
+
:tinytext, :mediumtext, :longtext, :unsigned_integer, :unsigned_bigint,
|
56
|
+
:unsigned_float, :unsigned_decimal
|
49
57
|
end
|
50
58
|
end
|
51
59
|
|
@@ -10,6 +10,10 @@ module ActiveRecord
|
|
10
10
|
spec[:unsigned] = "true" if column.unsigned?
|
11
11
|
spec[:auto_increment] = "true" if column.auto_increment?
|
12
12
|
|
13
|
+
if /\A(?<size>tiny|medium|long)(?:text|blob)/ =~ column.sql_type
|
14
|
+
spec = { size: size.to_sym.inspect }.merge!(spec)
|
15
|
+
end
|
16
|
+
|
13
17
|
if @connection.supports_virtual_columns? && column.virtual?
|
14
18
|
spec[:as] = extract_expression_for_virtual_column(column)
|
15
19
|
spec[:stored] = "true" if /\b(?:STORED|PERSISTENT)\b/.match?(column.extra)
|
@@ -37,13 +41,15 @@ module ActiveRecord
|
|
37
41
|
case column.sql_type
|
38
42
|
when /\Atimestamp\b/
|
39
43
|
:timestamp
|
40
|
-
when "tinyblob"
|
41
|
-
:blob
|
42
44
|
else
|
43
45
|
super
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
49
|
+
def schema_limit(column)
|
50
|
+
super unless /\A(?:tiny|medium|long)?(?:text|blob)/.match?(column.sql_type)
|
51
|
+
end
|
52
|
+
|
47
53
|
def schema_precision(column)
|
48
54
|
super unless /\A(?:date)?time(?:stamp)?\b/.match?(column.sql_type) && column.precision == 0
|
49
55
|
end
|
@@ -97,6 +97,30 @@ module ActiveRecord
|
|
97
97
|
MySQL::SchemaDumper.create(self, options)
|
98
98
|
end
|
99
99
|
|
100
|
+
# Maps logical Rails types to MySQL-specific data types.
|
101
|
+
def type_to_sql(type, limit: nil, precision: nil, scale: nil, size: limit_to_size(limit, type), unsigned: nil, **)
|
102
|
+
sql =
|
103
|
+
case type.to_s
|
104
|
+
when "integer"
|
105
|
+
integer_to_sql(limit)
|
106
|
+
when "text"
|
107
|
+
type_with_size_to_sql("text", size)
|
108
|
+
when "blob"
|
109
|
+
type_with_size_to_sql("blob", size)
|
110
|
+
when "binary"
|
111
|
+
if (0..0xfff) === limit
|
112
|
+
"varbinary(#{limit})"
|
113
|
+
else
|
114
|
+
type_with_size_to_sql("blob", size)
|
115
|
+
end
|
116
|
+
else
|
117
|
+
super
|
118
|
+
end
|
119
|
+
|
120
|
+
sql = "#{sql} unsigned" if unsigned && type != :primary_key
|
121
|
+
sql
|
122
|
+
end
|
123
|
+
|
100
124
|
private
|
101
125
|
CHARSETS_OF_4BYTES_MAXLEN = ["utf8mb4", "utf16", "utf16le", "utf32"]
|
102
126
|
|
@@ -127,7 +151,7 @@ module ActiveRecord
|
|
127
151
|
end
|
128
152
|
|
129
153
|
def create_table_definition(*args)
|
130
|
-
MySQL::TableDefinition.new(*args)
|
154
|
+
MySQL::TableDefinition.new(self, *args)
|
131
155
|
end
|
132
156
|
|
133
157
|
def new_column_from_field(table_name, field)
|
@@ -197,6 +221,40 @@ module ActiveRecord
|
|
197
221
|
schema, name = nil, schema unless name
|
198
222
|
[schema, name]
|
199
223
|
end
|
224
|
+
|
225
|
+
def type_with_size_to_sql(type, size)
|
226
|
+
case size&.to_s
|
227
|
+
when nil, "tiny", "medium", "long"
|
228
|
+
"#{size}#{type}"
|
229
|
+
else
|
230
|
+
raise ArgumentError,
|
231
|
+
"#{size.inspect} is invalid :size value. Only :tiny, :medium, and :long are allowed."
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def limit_to_size(limit, type)
|
236
|
+
case type.to_s
|
237
|
+
when "text", "blob", "binary"
|
238
|
+
case limit
|
239
|
+
when 0..0xff; "tiny"
|
240
|
+
when nil, 0x100..0xffff; nil
|
241
|
+
when 0x10000..0xffffff; "medium"
|
242
|
+
when 0x1000000..0xffffffff; "long"
|
243
|
+
else raise ActiveRecordError, "No #{type} type has byte size #{limit}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def integer_to_sql(limit)
|
249
|
+
case limit
|
250
|
+
when 1; "tinyint"
|
251
|
+
when 2; "smallint"
|
252
|
+
when 3; "mediumint"
|
253
|
+
when nil, 4; "int"
|
254
|
+
when 5..8; "bigint"
|
255
|
+
else raise ActiveRecordError, "No integer type has byte size #{limit}. Use a decimal with scale 0 instead."
|
256
|
+
end
|
257
|
+
end
|
200
258
|
end
|
201
259
|
end
|
202
260
|
end
|
@@ -138,7 +138,7 @@ module ActiveRecord
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def encode_range(range)
|
141
|
-
"[#{type_cast_range_value(range.
|
141
|
+
"[#{type_cast_range_value(range.begin)},#{type_cast_range_value(range.end)}#{range.exclude_end? ? ')' : ']'}"
|
142
142
|
end
|
143
143
|
|
144
144
|
def determine_encoding_of_strings_in_array(value)
|
@@ -17,6 +17,42 @@ module ActiveRecord
|
|
17
17
|
"VALIDATE CONSTRAINT #{quote_column_name(name)}"
|
18
18
|
end
|
19
19
|
|
20
|
+
def visit_ChangeColumnDefinition(o)
|
21
|
+
column = o.column
|
22
|
+
column.sql_type = type_to_sql(column.type, column.options)
|
23
|
+
quoted_column_name = quote_column_name(o.name)
|
24
|
+
|
25
|
+
change_column_sql = +"ALTER COLUMN #{quoted_column_name} TYPE #{column.sql_type}"
|
26
|
+
|
27
|
+
options = column_options(column)
|
28
|
+
|
29
|
+
if options[:collation]
|
30
|
+
change_column_sql << " COLLATE \"#{options[:collation]}\""
|
31
|
+
end
|
32
|
+
|
33
|
+
if options[:using]
|
34
|
+
change_column_sql << " USING #{options[:using]}"
|
35
|
+
elsif options[:cast_as]
|
36
|
+
cast_as_type = type_to_sql(options[:cast_as], options)
|
37
|
+
change_column_sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
|
38
|
+
end
|
39
|
+
|
40
|
+
if options.key?(:default)
|
41
|
+
if options[:default].nil?
|
42
|
+
change_column_sql << ", ALTER COLUMN #{quoted_column_name} DROP DEFAULT"
|
43
|
+
else
|
44
|
+
quoted_default = quote_default_expression(options[:default], column)
|
45
|
+
change_column_sql << ", ALTER COLUMN #{quoted_column_name} SET DEFAULT #{quoted_default}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if options.key?(:null)
|
50
|
+
change_column_sql << ", ALTER COLUMN #{quoted_column_name} #{options[:null] ? 'DROP' : 'SET'} NOT NULL"
|
51
|
+
end
|
52
|
+
|
53
|
+
change_column_sql
|
54
|
+
end
|
55
|
+
|
20
56
|
def add_column_options!(sql, options)
|
21
57
|
if options[:collation]
|
22
58
|
sql << " COLLATE \"#{options[:collation]}\""
|