activerecord 4.0.0 → 4.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 +326 -3
- data/README.rdoc +1 -1
- data/lib/active_record.rb +1 -0
- data/lib/active_record/association_relation.rb +18 -0
- data/lib/active_record/associations/association.rb +11 -3
- data/lib/active_record/associations/builder/belongs_to.rb +4 -2
- data/lib/active_record/associations/collection_association.rb +8 -8
- data/lib/active_record/associations/collection_proxy.rb +2 -4
- data/lib/active_record/associations/has_many_association.rb +2 -2
- data/lib/active_record/associations/has_one_association.rb +3 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +2 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -1
- data/lib/active_record/associations/preloader.rb +3 -2
- data/lib/active_record/attribute_methods.rb +26 -2
- data/lib/active_record/attribute_methods/read.rb +15 -9
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +2 -0
- data/lib/active_record/autosave_association.rb +8 -8
- data/lib/active_record/callbacks.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +7 -7
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +12 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +16 -2
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +3 -1
- data/lib/active_record/connection_adapters/column.rb +12 -11
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +9 -3
- data/lib/active_record/connection_adapters/mysql_adapter.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/cast.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +7 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +7 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +19 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +8 -5
- data/lib/active_record/core.rb +18 -18
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/fixtures.rb +2 -2
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +4 -1
- data/lib/active_record/model_schema.rb +27 -17
- data/lib/active_record/null_relation.rb +1 -5
- data/lib/active_record/persistence.rb +16 -5
- data/lib/active_record/railtie.rb +1 -0
- data/lib/active_record/railties/databases.rake +4 -1
- data/lib/active_record/reflection.rb +1 -1
- data/lib/active_record/relation.rb +1 -1
- data/lib/active_record/relation/batches.rb +2 -2
- data/lib/active_record/relation/calculations.rb +1 -0
- data/lib/active_record/relation/finder_methods.rb +10 -10
- data/lib/active_record/relation/merger.rb +31 -28
- data/lib/active_record/relation/query_methods.rb +13 -11
- data/lib/active_record/result.rb +15 -1
- data/lib/active_record/sanitization.rb +13 -3
- data/lib/active_record/schema_dumper.rb +5 -1
- data/lib/active_record/tasks/database_tasks.rb +2 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +1 -1
- data/lib/active_record/transactions.rb +5 -5
- data/lib/active_record/validations/uniqueness.rb +2 -2
- data/lib/active_record/version.rb +1 -1
- metadata +10 -9
@@ -34,7 +34,9 @@ module ActiveRecord::Associations::Builder
|
|
34
34
|
def belongs_to_counter_cache_before_destroy_for_#{name}
|
35
35
|
unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == #{foreign_key.to_sym.inspect}
|
36
36
|
record = #{name}
|
37
|
-
|
37
|
+
if record && !self.destroyed?
|
38
|
+
record.class.decrement_counter(:#{cache_column}, record.id)
|
39
|
+
end
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
@@ -68,7 +70,7 @@ module ActiveRecord::Associations::Builder
|
|
68
70
|
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
69
71
|
def belongs_to_touch_after_save_or_destroy_for_#{name}
|
70
72
|
foreign_key_field = #{reflection.foreign_key.inspect}
|
71
|
-
old_foreign_id =
|
73
|
+
old_foreign_id = changed_attributes[foreign_key_field]
|
72
74
|
|
73
75
|
if old_foreign_id
|
74
76
|
klass = association(#{name.inspect}).klass
|
@@ -81,15 +81,15 @@ module ActiveRecord
|
|
81
81
|
else
|
82
82
|
if options[:finder_sql]
|
83
83
|
find_by_scan(*args)
|
84
|
-
elsif options[:inverse_of]
|
85
|
-
|
86
|
-
raise RecordNotFound, "Couldn't find #{scope.klass.name} without an ID" if
|
84
|
+
elsif options[:inverse_of] && loaded?
|
85
|
+
args_flatten = args.flatten
|
86
|
+
raise RecordNotFound, "Couldn't find #{scope.klass.name} without an ID" if args_flatten.blank?
|
87
87
|
|
88
88
|
result = find_by_scan(*args)
|
89
89
|
|
90
90
|
result_size = Array(result).size
|
91
|
-
if !result || result_size !=
|
92
|
-
scope.raise_record_not_found_exception!(
|
91
|
+
if !result || result_size != args_flatten.size
|
92
|
+
scope.raise_record_not_found_exception!(args_flatten, result_size, args_flatten.size)
|
93
93
|
else
|
94
94
|
result
|
95
95
|
end
|
@@ -583,14 +583,14 @@ module ActiveRecord
|
|
583
583
|
# specified, then #find scans the entire collection.
|
584
584
|
def find_by_scan(*args)
|
585
585
|
expects_array = args.first.kind_of?(Array)
|
586
|
-
ids = args.flatten.compact.map{ |arg| arg.
|
586
|
+
ids = args.flatten.compact.map{ |arg| arg.to_s }.uniq
|
587
587
|
|
588
588
|
if ids.size == 1
|
589
589
|
id = ids.first
|
590
|
-
record = load_target.detect { |r| id == r.id }
|
590
|
+
record = load_target.detect { |r| id == r.id.to_s }
|
591
591
|
expects_array ? [ record ] : record
|
592
592
|
else
|
593
|
-
load_target.select { |r| ids.include?(r.id) }
|
593
|
+
load_target.select { |r| ids.include?(r.id.to_s) }
|
594
594
|
end
|
595
595
|
end
|
596
596
|
|
@@ -830,7 +830,7 @@ module ActiveRecord
|
|
830
830
|
# person.pets.include?(Pet.find(20)) # => true
|
831
831
|
# person.pets.include?(Pet.find(21)) # => false
|
832
832
|
def include?(record)
|
833
|
-
|
833
|
+
!!@association.include?(record)
|
834
834
|
end
|
835
835
|
|
836
836
|
def proxy_association
|
@@ -847,9 +847,7 @@ module ActiveRecord
|
|
847
847
|
|
848
848
|
# Returns a <tt>Relation</tt> object for the records in this association
|
849
849
|
def scope
|
850
|
-
@association.scope
|
851
|
-
scope.proxy_association = @association
|
852
|
-
end
|
850
|
+
@association.scope
|
853
851
|
end
|
854
852
|
|
855
853
|
# :nodoc:
|
@@ -32,6 +32,7 @@ module ActiveRecord
|
|
32
32
|
|
33
33
|
def insert_record(record, validate = true, raise = false)
|
34
34
|
set_owner_attributes(record)
|
35
|
+
set_inverse_instance(record)
|
35
36
|
|
36
37
|
if raise
|
37
38
|
record.save!(:validate => validate)
|
@@ -115,8 +116,7 @@ module ActiveRecord
|
|
115
116
|
if records == :all
|
116
117
|
scope = self.scope
|
117
118
|
else
|
118
|
-
|
119
|
-
scope = self.scope.where(reflection.association_primary_key => keys)
|
119
|
+
scope = self.scope.where(reflection.klass.primary_key => records)
|
120
120
|
end
|
121
121
|
|
122
122
|
if method == :delete_all
|
@@ -27,6 +27,8 @@ module ActiveRecord
|
|
27
27
|
|
28
28
|
return self.target if !(target || record)
|
29
29
|
if (target != record) || record.changed?
|
30
|
+
save &&= owner.persisted?
|
31
|
+
|
30
32
|
transaction_if(save) do
|
31
33
|
remove_target!(options[:dependent]) if target && !target.destroyed?
|
32
34
|
|
@@ -34,7 +36,7 @@ module ActiveRecord
|
|
34
36
|
set_owner_attributes(record)
|
35
37
|
set_inverse_instance(record)
|
36
38
|
|
37
|
-
if
|
39
|
+
if save && !record.save
|
38
40
|
nullify_owner_attributes(record)
|
39
41
|
set_owner_attributes(target) if target
|
40
42
|
raise RecordNotSaved, "Failed to save the new associated #{reflection.name}."
|
@@ -106,6 +106,8 @@ module ActiveRecord
|
|
106
106
|
]
|
107
107
|
end
|
108
108
|
|
109
|
+
scope_chain_items += [reflection.klass.send(:build_default_scope)].compact
|
110
|
+
|
109
111
|
scope_chain_items.each do |item|
|
110
112
|
unless item.is_a?(Relation)
|
111
113
|
item = ActiveRecord::Relation.new(reflection.klass, table).instance_exec(self, &item)
|
@@ -62,7 +62,20 @@ module ActiveRecord
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def extract_record(row)
|
65
|
-
|
65
|
+
# This code is performance critical as it is called per row.
|
66
|
+
# see: https://github.com/rails/rails/pull/12185
|
67
|
+
hash = {}
|
68
|
+
|
69
|
+
index = 0
|
70
|
+
length = column_names_with_alias.length
|
71
|
+
|
72
|
+
while index < length
|
73
|
+
column_name, alias_name = column_names_with_alias[index]
|
74
|
+
hash[column_name] = row[alias_name]
|
75
|
+
index += 1
|
76
|
+
end
|
77
|
+
|
78
|
+
hash
|
66
79
|
end
|
67
80
|
|
68
81
|
def record_id(row)
|
@@ -141,10 +141,11 @@ module ActiveRecord
|
|
141
141
|
|
142
142
|
def records_by_reflection(association)
|
143
143
|
records.group_by do |record|
|
144
|
-
|
144
|
+
record_class = record.class
|
145
|
+
reflection = record_class.reflections[association]
|
145
146
|
|
146
147
|
unless reflection
|
147
|
-
raise ActiveRecord::ConfigurationError, "Association named '#{association}' was not found; " \
|
148
|
+
raise ActiveRecord::ConfigurationError, "Association named '#{association}' was not found on #{record_class.name}; " \
|
148
149
|
"perhaps you misspelled it?"
|
149
150
|
end
|
150
151
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/enumerable'
|
2
|
+
require 'mutex_m'
|
2
3
|
|
3
4
|
module ActiveRecord
|
4
5
|
# = Active Record Attribute Methods
|
@@ -7,6 +8,7 @@ module ActiveRecord
|
|
7
8
|
include ActiveModel::AttributeMethods
|
8
9
|
|
9
10
|
included do
|
11
|
+
initialize_generated_modules
|
10
12
|
include Read
|
11
13
|
include Write
|
12
14
|
include BeforeTypeCast
|
@@ -18,12 +20,34 @@ module ActiveRecord
|
|
18
20
|
end
|
19
21
|
|
20
22
|
module ClassMethods
|
23
|
+
def inherited(child_class) #:nodoc:
|
24
|
+
child_class.initialize_generated_modules
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize_generated_modules # :nodoc:
|
29
|
+
@generated_attribute_methods = Module.new {
|
30
|
+
extend Mutex_m
|
31
|
+
|
32
|
+
const_set :AttrNames, Module.new {
|
33
|
+
def self.set_name_cache(name, value)
|
34
|
+
const_name = "ATTR_#{name}"
|
35
|
+
unless const_defined? const_name
|
36
|
+
const_set const_name, value.dup.freeze
|
37
|
+
end
|
38
|
+
end
|
39
|
+
}
|
40
|
+
}
|
41
|
+
@attribute_methods_generated = false
|
42
|
+
include @generated_attribute_methods
|
43
|
+
end
|
44
|
+
|
21
45
|
# Generates all the attribute related methods for columns in the database
|
22
46
|
# accessors, mutators and query methods.
|
23
47
|
def define_attribute_methods # :nodoc:
|
24
48
|
# Use a mutex; we don't want two thread simultaneously trying to define
|
25
49
|
# attribute methods.
|
26
|
-
|
50
|
+
generated_attribute_methods.synchronize do
|
27
51
|
return if attribute_methods_generated?
|
28
52
|
superclass.define_attribute_methods unless self == base_class
|
29
53
|
super(column_names)
|
@@ -32,7 +56,7 @@ module ActiveRecord
|
|
32
56
|
end
|
33
57
|
|
34
58
|
def attribute_methods_generated? # :nodoc:
|
35
|
-
@attribute_methods_generated
|
59
|
+
@attribute_methods_generated
|
36
60
|
end
|
37
61
|
|
38
62
|
def undefine_attribute_methods # :nodoc:
|
@@ -33,8 +33,11 @@ module ActiveRecord
|
|
33
33
|
protected
|
34
34
|
|
35
35
|
# We want to generate the methods via module_eval rather than
|
36
|
-
# define_method, because define_method is slower on dispatch
|
37
|
-
#
|
36
|
+
# define_method, because define_method is slower on dispatch.
|
37
|
+
# Evaluating many similar methods may use more memory as the instruction
|
38
|
+
# sequences are duplicated and cached (in MRI). define_method may
|
39
|
+
# be slower on dispatch, but if you're careful about the closure
|
40
|
+
# created, then define_method will consume much less memory.
|
38
41
|
#
|
39
42
|
# But sometimes the database might return columns with
|
40
43
|
# characters that are not allowed in normal method names (like
|
@@ -49,6 +52,8 @@ module ActiveRecord
|
|
49
52
|
# key the @attributes_cache in read_attribute.
|
50
53
|
def define_method_attribute(name)
|
51
54
|
safe_name = name.unpack('h*').first
|
55
|
+
generated_attribute_methods::AttrNames.set_name_cache safe_name, name
|
56
|
+
|
52
57
|
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
53
58
|
def __temp__#{safe_name}
|
54
59
|
read_attribute(AttrNames::ATTR_#{safe_name}) { |n| missing_attribute(n, caller) }
|
@@ -77,13 +82,14 @@ module ActiveRecord
|
|
77
82
|
# We use #[] first as a perf optimization for non-nil values. See https://gist.github.com/jonleighton/3552829.
|
78
83
|
name = attr_name.to_s
|
79
84
|
@attributes_cache[name] || @attributes_cache.fetch(name) {
|
80
|
-
column = @
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
85
|
+
column = @column_types_override[name] if @column_types_override
|
86
|
+
column ||= @column_types[name]
|
87
|
+
|
88
|
+
return @attributes.fetch(name) {
|
89
|
+
if name == 'id' && self.class.primary_key != name
|
90
|
+
read_attribute(self.class.primary_key)
|
91
|
+
end
|
92
|
+
} unless column
|
87
93
|
|
88
94
|
value = @attributes.fetch(name) {
|
89
95
|
return block_given? ? yield(name) : nil
|
@@ -51,7 +51,7 @@ module ActiveRecord
|
|
51
51
|
def create_time_zone_conversion_attribute?(name, column)
|
52
52
|
time_zone_aware_attributes &&
|
53
53
|
!self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) &&
|
54
|
-
|
54
|
+
(:datetime == column.type || :timestamp == column.type)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -14,6 +14,8 @@ module ActiveRecord
|
|
14
14
|
# this code.
|
15
15
|
def define_method_attribute=(name)
|
16
16
|
safe_name = name.unpack('h*').first
|
17
|
+
generated_attribute_methods::AttrNames.set_name_cache safe_name, name
|
18
|
+
|
17
19
|
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
18
20
|
def __temp__#{safe_name}=(value)
|
19
21
|
write_attribute(AttrNames::ATTR_#{safe_name}, value)
|
@@ -335,15 +335,19 @@ module ActiveRecord
|
|
335
335
|
autosave = reflection.options[:autosave]
|
336
336
|
|
337
337
|
if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave)
|
338
|
-
|
338
|
+
|
339
|
+
if autosave
|
340
|
+
records_to_destroy = records.select(&:marked_for_destruction?)
|
341
|
+
records_to_destroy.each { |record| association.destroy(record) }
|
342
|
+
records -= records_to_destroy
|
343
|
+
end
|
344
|
+
|
339
345
|
records.each do |record|
|
340
346
|
next if record.destroyed?
|
341
347
|
|
342
348
|
saved = true
|
343
349
|
|
344
|
-
if autosave && record.
|
345
|
-
records_to_destroy << record
|
346
|
-
elsif autosave != false && (@new_record_before_save || record.new_record?)
|
350
|
+
if autosave != false && (@new_record_before_save || record.new_record?)
|
347
351
|
if autosave
|
348
352
|
saved = association.insert_record(record, false)
|
349
353
|
else
|
@@ -355,10 +359,6 @@ module ActiveRecord
|
|
355
359
|
|
356
360
|
raise ActiveRecord::Rollback unless saved
|
357
361
|
end
|
358
|
-
|
359
|
-
records_to_destroy.each do |record|
|
360
|
-
association.destroy(record)
|
361
|
-
end
|
362
362
|
end
|
363
363
|
|
364
364
|
# reconstruct the scope now that we know the owner's id
|
@@ -23,11 +23,14 @@ module ActiveRecord
|
|
23
23
|
# Check out <tt>ActiveRecord::Transactions</tt> for more details about <tt>after_commit</tt> and
|
24
24
|
# <tt>after_rollback</tt>.
|
25
25
|
#
|
26
|
+
# Additionally, an <tt>after_touch</tt> callback is triggered whenever an
|
27
|
+
# object is touched.
|
28
|
+
#
|
26
29
|
# Lastly an <tt>after_find</tt> and <tt>after_initialize</tt> callback is triggered for each object that
|
27
30
|
# is found and instantiated by a finder, with <tt>after_initialize</tt> being triggered after new objects
|
28
31
|
# are instantiated as well.
|
29
32
|
#
|
30
|
-
#
|
33
|
+
# There are nineteen callbacks in total, which give you immense power to react and prepare for each state in the
|
31
34
|
# Active Record life cycle. The sequence for calling <tt>Base#save</tt> for an existing record is similar,
|
32
35
|
# except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
|
33
36
|
#
|
@@ -377,14 +377,14 @@ module ActiveRecord
|
|
377
377
|
update_sql(sql, name)
|
378
378
|
end
|
379
379
|
|
380
|
-
|
381
|
-
|
382
|
-
|
380
|
+
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
381
|
+
[sql, binds]
|
382
|
+
end
|
383
383
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
384
|
+
def last_inserted_id(result)
|
385
|
+
row = result.rows.first
|
386
|
+
row && row.first
|
387
|
+
end
|
388
388
|
end
|
389
389
|
end
|
390
390
|
end
|
@@ -706,12 +706,21 @@ module ActiveRecord
|
|
706
706
|
end
|
707
707
|
|
708
708
|
# SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
|
709
|
-
# Both PostgreSQL and Oracle overrides this for custom DISTINCT syntax.
|
710
709
|
#
|
711
|
-
# distinct("posts.id", "posts.created_at desc")
|
710
|
+
# distinct("posts.id", ["posts.created_at desc"])
|
712
711
|
#
|
713
712
|
def distinct(columns, order_by)
|
714
|
-
"
|
713
|
+
ActiveSupport::Deprecation.warn("#distinct is deprecated and shall be removed from future releases.")
|
714
|
+
"DISTINCT #{columns_for_distinct(columns, order_by)}"
|
715
|
+
end
|
716
|
+
|
717
|
+
# Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT.
|
718
|
+
# Both PostgreSQL and Oracle overrides this for custom DISTINCT syntax - they
|
719
|
+
# require the order columns appear in the SELECT.
|
720
|
+
#
|
721
|
+
# columns_for_distinct("posts.id", ["posts.created_at desc"])
|
722
|
+
def columns_for_distinct(columns, orders) # :nodoc:
|
723
|
+
columns
|
715
724
|
end
|
716
725
|
|
717
726
|
# Adds timestamps (+created_at+ and +updated_at+) columns to the named table.
|
@@ -99,6 +99,7 @@ module ActiveRecord
|
|
99
99
|
@query_cache_enabled = false
|
100
100
|
@schema_cache = SchemaCache.new self
|
101
101
|
@visitor = nil
|
102
|
+
@prepared_statements = false
|
102
103
|
end
|
103
104
|
|
104
105
|
def valid_type?(type)
|
@@ -197,10 +198,11 @@ module ActiveRecord
|
|
197
198
|
end
|
198
199
|
|
199
200
|
def unprepared_statement
|
200
|
-
|
201
|
+
old_prepared_statements, @prepared_statements = @prepared_statements, false
|
202
|
+
old_visitor, @visitor = @visitor, unprepared_visitor
|
201
203
|
yield
|
202
204
|
ensure
|
203
|
-
@visitor =
|
205
|
+
@visitor, @prepared_statements = old_visitor, old_prepared_statements
|
204
206
|
end
|
205
207
|
|
206
208
|
# Returns the human-readable name of the adapter. Use mixed case - one
|
@@ -280,6 +282,14 @@ module ActiveRecord
|
|
280
282
|
false
|
281
283
|
end
|
282
284
|
|
285
|
+
# This is meant to be implemented by the adapters that support extensions
|
286
|
+
def disable_extension(name)
|
287
|
+
end
|
288
|
+
|
289
|
+
# This is meant to be implemented by the adapters that support extensions
|
290
|
+
def enable_extension(name)
|
291
|
+
end
|
292
|
+
|
283
293
|
# A list of extensions, to be filled in by adapters that support them. At
|
284
294
|
# the moment only postgresql does.
|
285
295
|
def extensions
|
@@ -435,6 +445,10 @@ module ActiveRecord
|
|
435
445
|
# override in derived class
|
436
446
|
ActiveRecord::StatementInvalid.new(message, exception)
|
437
447
|
end
|
448
|
+
|
449
|
+
def without_prepared_statement?(binds)
|
450
|
+
!@prepared_statements || binds.empty?
|
451
|
+
end
|
438
452
|
end
|
439
453
|
end
|
440
454
|
end
|
@@ -165,6 +165,7 @@ module ActiveRecord
|
|
165
165
|
@quoted_column_names, @quoted_table_names = {}, {}
|
166
166
|
|
167
167
|
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
168
|
+
@prepared_statements = true
|
168
169
|
@visitor = Arel::Visitors::MySQL.new self
|
169
170
|
else
|
170
171
|
@visitor = unprepared_visitor
|
@@ -460,7 +461,8 @@ module ActiveRecord
|
|
460
461
|
sql = "SHOW FULL FIELDS FROM #{quote_table_name(table_name)}"
|
461
462
|
execute_and_free(sql, 'SCHEMA') do |result|
|
462
463
|
each_hash(result).map do |field|
|
463
|
-
|
464
|
+
field_name = set_field_encoding(field[:Field])
|
465
|
+
new_column(field_name, field[:Default], field[:Type], field[:Null] == "YES", field[:Collation], field[:Extra])
|
464
466
|
end
|
465
467
|
end
|
466
468
|
end
|