activerecord 5.2.0 → 5.2.8.1
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 +361 -0
- data/lib/active_record/association_relation.rb +3 -3
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +25 -10
- data/lib/active_record/associations/belongs_to_association.rb +14 -5
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -1
- data/lib/active_record/associations/builder/belongs_to.rb +11 -2
- data/lib/active_record/associations/builder/collection_association.rb +2 -2
- data/lib/active_record/associations/collection_association.rb +19 -15
- data/lib/active_record/associations/collection_proxy.rb +8 -34
- data/lib/active_record/associations/has_many_association.rb +9 -0
- data/lib/active_record/associations/has_many_through_association.rb +29 -12
- data/lib/active_record/associations/has_one_association.rb +8 -0
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -24
- data/lib/active_record/associations/join_dependency/join_part.rb +7 -0
- data/lib/active_record/associations/join_dependency.rb +39 -64
- data/lib/active_record/associations/preloader.rb +1 -1
- data/lib/active_record/associations/singular_association.rb +4 -10
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +9 -9
- data/lib/active_record/attribute_methods/dirty.rb +15 -10
- data/lib/active_record/attribute_methods/read.rb +1 -1
- data/lib/active_record/autosave_association.rb +27 -8
- data/lib/active_record/callbacks.rb +4 -0
- data/lib/active_record/coders/yaml_column.rb +13 -1
- data/lib/active_record/collection_cache_key.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +36 -11
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +19 -6
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -3
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +7 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +6 -15
- data/lib/active_record/connection_adapters/abstract/transaction.rb +23 -14
- data/lib/active_record/connection_adapters/abstract_adapter.rb +3 -1
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +18 -19
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -2
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -2
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +11 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +9 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +3 -6
- data/lib/active_record/core.rb +12 -1
- data/lib/active_record/counter_cache.rb +17 -13
- data/lib/active_record/enum.rb +1 -0
- data/lib/active_record/errors.rb +18 -12
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/log_subscriber.rb +1 -1
- data/lib/active_record/migration/compatibility.rb +15 -15
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/model_schema.rb +1 -1
- data/lib/active_record/persistence.rb +6 -5
- data/lib/active_record/query_cache.rb +4 -11
- data/lib/active_record/querying.rb +1 -1
- data/lib/active_record/railtie.rb +19 -3
- data/lib/active_record/reflection.rb +10 -14
- data/lib/active_record/relation/calculations.rb +16 -12
- data/lib/active_record/relation/delegation.rb +30 -0
- data/lib/active_record/relation/finder_methods.rb +10 -8
- data/lib/active_record/relation/merger.rb +10 -11
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder.rb +20 -14
- data/lib/active_record/relation/query_attribute.rb +5 -3
- data/lib/active_record/relation/query_methods.rb +50 -22
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation.rb +39 -20
- data/lib/active_record/scoping/default.rb +2 -2
- data/lib/active_record/scoping/named.rb +2 -0
- data/lib/active_record/statement_cache.rb +2 -2
- data/lib/active_record/tasks/database_tasks.rb +1 -1
- data/lib/active_record/timestamp.rb +8 -1
- data/lib/active_record/transactions.rb +24 -21
- data/lib/active_record/type/serialized.rb +4 -0
- metadata +12 -13
@@ -80,8 +80,8 @@ module ActiveRecord
|
|
80
80
|
|
81
81
|
def new_column_from_field(table_name, field)
|
82
82
|
type_metadata = fetch_type_metadata(field[:Type], field[:Extra])
|
83
|
-
if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\(
|
84
|
-
default, default_function = nil,
|
83
|
+
if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\([0-6]?\))?\z/i.match?(field[:Default])
|
84
|
+
default, default_function = nil, field[:Default]
|
85
85
|
else
|
86
86
|
default, default_function = field[:Default], nil
|
87
87
|
end
|
@@ -33,7 +33,13 @@ module ActiveRecord
|
|
33
33
|
|
34
34
|
def cast(value)
|
35
35
|
if value.is_a?(::String)
|
36
|
-
value =
|
36
|
+
value = begin
|
37
|
+
@pg_decoder.decode(value)
|
38
|
+
rescue TypeError
|
39
|
+
# malformed array string is treated as [], will raise in PG 2.0 gem
|
40
|
+
# this keeps a consistent implementation
|
41
|
+
[]
|
42
|
+
end
|
37
43
|
end
|
38
44
|
type_cast_array(value, :cast)
|
39
45
|
end
|
@@ -66,6 +72,10 @@ module ActiveRecord
|
|
66
72
|
deserialize(raw_old_value) != new_value
|
67
73
|
end
|
68
74
|
|
75
|
+
def force_equality?(value)
|
76
|
+
value.is_a?(::Array)
|
77
|
+
end
|
78
|
+
|
69
79
|
private
|
70
80
|
|
71
81
|
def type_cast_array(value, method)
|
@@ -26,9 +26,9 @@ module ActiveRecord
|
|
26
26
|
|
27
27
|
value = value.sub(/^\((.+)\)$/, '-\1') # (4)
|
28
28
|
case value
|
29
|
-
when /^-?\D
|
29
|
+
when /^-?\D*+[\d,]+\.\d{2}$/ # (1)
|
30
30
|
value.gsub!(/[^-\d.]/, "")
|
31
|
-
when /^-?\D
|
31
|
+
when /^-?\D*+[\d.]+,\d{2}$/ # (2)
|
32
32
|
value.gsub!(/[^-\d,]/, "").sub!(/,/, ".")
|
33
33
|
end
|
34
34
|
|
@@ -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}".dup
|
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]}\""
|
@@ -124,7 +124,7 @@ module ActiveRecord
|
|
124
124
|
|
125
125
|
# add info on sort order (only desc order is explicitly specified, asc is the default)
|
126
126
|
# and non-default opclasses
|
127
|
-
expressions.scan(/(?<column>\w+)
|
127
|
+
expressions.scan(/(?<column>\w+)"?\s?(?<opclass>\w+_ops)?\s?(?<desc>DESC)?\s?(?<nulls>NULLS (?:FIRST|LAST))?/).each do |column, opclass, desc, nulls|
|
128
128
|
opclasses[column] = opclass.to_sym if opclass
|
129
129
|
if nulls
|
130
130
|
orders[column] = [desc, nulls].compact.join(" ")
|
@@ -683,34 +683,20 @@ module ActiveRecord
|
|
683
683
|
end
|
684
684
|
end
|
685
685
|
|
686
|
-
def
|
687
|
-
|
688
|
-
|
689
|
-
sql = "ALTER COLUMN #{quoted_column_name} TYPE #{sql_type}".dup
|
690
|
-
if options[:collation]
|
691
|
-
sql << " COLLATE \"#{options[:collation]}\""
|
692
|
-
end
|
693
|
-
if options[:using]
|
694
|
-
sql << " USING #{options[:using]}"
|
695
|
-
elsif options[:cast_as]
|
696
|
-
cast_as_type = type_to_sql(options[:cast_as], options)
|
697
|
-
sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
|
698
|
-
end
|
699
|
-
|
700
|
-
sql
|
686
|
+
def add_column_for_alter(table_name, column_name, type, options = {})
|
687
|
+
return super unless options.key?(:comment)
|
688
|
+
[super, Proc.new { change_column_comment(table_name, column_name, options[:comment]) }]
|
701
689
|
end
|
702
690
|
|
703
691
|
def change_column_for_alter(table_name, column_name, type, options = {})
|
704
|
-
|
705
|
-
|
706
|
-
sqls
|
692
|
+
td = create_table_definition(table_name)
|
693
|
+
cd = td.new_column_definition(column_name, type, options)
|
694
|
+
sqls = [schema_creation.accept(ChangeColumnDefinition.new(cd, column_name))]
|
707
695
|
sqls << Proc.new { change_column_comment(table_name, column_name, options[:comment]) } if options.key?(:comment)
|
708
696
|
sqls
|
709
697
|
end
|
710
698
|
|
711
|
-
|
712
|
-
# Changes the default value of a table column.
|
713
|
-
def change_column_default_for_alter(table_name, column_name, default_or_changes) # :nodoc:
|
699
|
+
def change_column_default_for_alter(table_name, column_name, default_or_changes)
|
714
700
|
column = column_for(table_name, column_name)
|
715
701
|
return unless column
|
716
702
|
|
@@ -725,8 +711,8 @@ module ActiveRecord
|
|
725
711
|
end
|
726
712
|
end
|
727
713
|
|
728
|
-
def change_column_null_for_alter(table_name, column_name, null, default = nil)
|
729
|
-
"ALTER #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
|
714
|
+
def change_column_null_for_alter(table_name, column_name, null, default = nil)
|
715
|
+
"ALTER COLUMN #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
|
730
716
|
end
|
731
717
|
|
732
718
|
def add_timestamps_for_alter(table_name, options = {})
|
@@ -751,7 +737,7 @@ module ActiveRecord
|
|
751
737
|
|
752
738
|
def data_source_sql(name = nil, type: nil)
|
753
739
|
scope = quoted_scope(name, type: type)
|
754
|
-
scope[:type] ||= "'r','v','m','f'" # (r)elation/table, (v)iew, (m)aterialized view, (f)oreign table
|
740
|
+
scope[:type] ||= "'r','v','m','p','f'" # (r)elation/table, (v)iew, (m)aterialized view, (p)artitioned table, (f)oreign table
|
755
741
|
|
756
742
|
sql = "SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace".dup
|
757
743
|
sql << " WHERE n.nspname = #{scope[:schema]}"
|
@@ -765,7 +751,7 @@ module ActiveRecord
|
|
765
751
|
type = \
|
766
752
|
case type
|
767
753
|
when "BASE TABLE"
|
768
|
-
"'r'"
|
754
|
+
"'r','p'"
|
769
755
|
when "VIEW"
|
770
756
|
"'v','m'"
|
771
757
|
when "FOREIGN TABLE"
|
@@ -68,7 +68,7 @@ module ActiveRecord
|
|
68
68
|
# * <tt>"schema_name".table_name</tt>
|
69
69
|
# * <tt>"schema.name"."table name"</tt>
|
70
70
|
def extract_schema_qualified_name(string)
|
71
|
-
schema, table = string.scan(/[^"
|
71
|
+
schema, table = string.scan(/[^".]+|"[^"]*"/)
|
72
72
|
if table.nil?
|
73
73
|
table = schema
|
74
74
|
schema = nil
|
@@ -4,6 +4,14 @@
|
|
4
4
|
gem "pg", ">= 0.18", "< 2.0"
|
5
5
|
require "pg"
|
6
6
|
|
7
|
+
# Use async_exec instead of exec_params on pg versions before 1.1
|
8
|
+
class ::PG::Connection
|
9
|
+
unless self.public_method_defined?(:async_exec_params)
|
10
|
+
remove_method :exec_params
|
11
|
+
alias exec_params async_exec
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
7
15
|
require "active_record/connection_adapters/abstract_adapter"
|
8
16
|
require "active_record/connection_adapters/statement_pool"
|
9
17
|
require "active_record/connection_adapters/postgresql/column"
|
@@ -600,7 +608,7 @@ module ActiveRecord
|
|
600
608
|
type_casted_binds = type_casted_binds(binds)
|
601
609
|
log(sql, name, binds, type_casted_binds) do
|
602
610
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
603
|
-
@connection.
|
611
|
+
@connection.exec_params(sql, type_casted_binds)
|
604
612
|
end
|
605
613
|
end
|
606
614
|
end
|
@@ -12,11 +12,16 @@ module ActiveRecord
|
|
12
12
|
quote_column_name(attr)
|
13
13
|
end
|
14
14
|
|
15
|
+
def quote_table_name(name)
|
16
|
+
@quoted_table_names[name] ||= super.gsub(".", "\".\"").freeze
|
17
|
+
end
|
18
|
+
|
15
19
|
def quote_column_name(name)
|
16
20
|
@quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}").freeze
|
17
21
|
end
|
18
22
|
|
19
23
|
def quoted_time(value)
|
24
|
+
value = value.change(year: 2000, month: 1, day: 1)
|
20
25
|
quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ")
|
21
26
|
end
|
22
27
|
|
@@ -7,6 +7,10 @@ module ActiveRecord
|
|
7
7
|
# Returns an array of indexes for the given table.
|
8
8
|
def indexes(table_name)
|
9
9
|
exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").map do |row|
|
10
|
+
# Indexes SQLite creates implicitly for internal use start with "sqlite_".
|
11
|
+
# See https://www.sqlite.org/fileformat2.html#intschema
|
12
|
+
next if row["name"].starts_with?("sqlite_")
|
13
|
+
|
10
14
|
index_sql = query_value(<<-SQL, "SCHEMA")
|
11
15
|
SELECT sql
|
12
16
|
FROM sqlite_master
|
@@ -40,7 +44,7 @@ module ActiveRecord
|
|
40
44
|
where: where,
|
41
45
|
orders: orders
|
42
46
|
)
|
43
|
-
end
|
47
|
+
end.compact
|
44
48
|
end
|
45
49
|
|
46
50
|
def create_schema_dumper(options)
|
@@ -9,7 +9,7 @@ require "active_record/connection_adapters/sqlite3/schema_definitions"
|
|
9
9
|
require "active_record/connection_adapters/sqlite3/schema_dumper"
|
10
10
|
require "active_record/connection_adapters/sqlite3/schema_statements"
|
11
11
|
|
12
|
-
gem "sqlite3", "~> 1.3.6"
|
12
|
+
gem "sqlite3", "~> 1.3", ">= 1.3.6"
|
13
13
|
require "sqlite3"
|
14
14
|
|
15
15
|
module ActiveRecord
|
@@ -453,9 +453,6 @@ module ActiveRecord
|
|
453
453
|
def copy_table_indexes(from, to, rename = {})
|
454
454
|
indexes(from).each do |index|
|
455
455
|
name = index.name
|
456
|
-
# indexes sqlite creates for internal use start with `sqlite_` and
|
457
|
-
# don't need to be copied
|
458
|
-
next if name.starts_with?("sqlite_")
|
459
456
|
if to == "a#{from}"
|
460
457
|
name = "t#{name}"
|
461
458
|
elsif from == "a#{to}"
|
@@ -528,9 +525,9 @@ module ActiveRecord
|
|
528
525
|
result = exec_query(sql, "SCHEMA").first
|
529
526
|
|
530
527
|
if result
|
531
|
-
# Splitting with left parentheses and
|
528
|
+
# Splitting with left parentheses and discarding the first part will return all
|
532
529
|
# columns separated with comma(,).
|
533
|
-
columns_string = result["sql"].split("(").last
|
530
|
+
columns_string = result["sql"].split("(", 2).last
|
534
531
|
|
535
532
|
columns_string.split(",").each do |column_string|
|
536
533
|
# This regex will match the column name and collation type and will save
|
data/lib/active_record/core.rb
CHANGED
@@ -125,6 +125,16 @@ module ActiveRecord
|
|
125
125
|
|
126
126
|
mattr_accessor :belongs_to_required_by_default, instance_accessor: false
|
127
127
|
|
128
|
+
##
|
129
|
+
# :singleton-method:
|
130
|
+
# Application configurable boolean that instructs the YAML Coder to use
|
131
|
+
# an unsafe load if set to true.
|
132
|
+
mattr_accessor :use_yaml_unsafe_load, instance_writer: false, default: false
|
133
|
+
|
134
|
+
# Application configurable array that provides additional permitted classes
|
135
|
+
# to Psych safe_load in the YAML Coder
|
136
|
+
mattr_accessor :yaml_column_permitted_classes, instance_writer: false, default: []
|
137
|
+
|
128
138
|
class_attribute :default_connection_handler, instance_writer: false
|
129
139
|
|
130
140
|
def self.connection_handler
|
@@ -184,7 +194,8 @@ module ActiveRecord
|
|
184
194
|
end
|
185
195
|
|
186
196
|
def find_by(*args) # :nodoc:
|
187
|
-
return super if scope_attributes? || reflect_on_all_aggregations.any?
|
197
|
+
return super if scope_attributes? || reflect_on_all_aggregations.any? ||
|
198
|
+
columns_hash.key?(inheritance_column) && base_class != self
|
188
199
|
|
189
200
|
hash = args.first
|
190
201
|
|
@@ -47,8 +47,12 @@ module ActiveRecord
|
|
47
47
|
reflection = child_class._reflections.values.find { |e| e.belongs_to? && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
|
48
48
|
counter_name = reflection.counter_cache_column
|
49
49
|
|
50
|
-
updates = { counter_name
|
51
|
-
|
50
|
+
updates = { counter_name => object.send(counter_association).count(:all) }
|
51
|
+
|
52
|
+
if touch
|
53
|
+
names = touch if touch != true
|
54
|
+
updates.merge!(touch_attributes_with_time(*names))
|
55
|
+
end
|
52
56
|
|
53
57
|
unscoped.where(primary_key => object.id).update_all(updates)
|
54
58
|
end
|
@@ -68,8 +72,8 @@ module ActiveRecord
|
|
68
72
|
# * +counters+ - A Hash containing the names of the fields
|
69
73
|
# to update as keys and the amount to update the field by as values.
|
70
74
|
# * <tt>:touch</tt> option - Touch timestamp columns when updating.
|
71
|
-
#
|
72
|
-
#
|
75
|
+
# If attribute names are passed, they are updated along with updated_at/on
|
76
|
+
# attributes.
|
73
77
|
#
|
74
78
|
# ==== Examples
|
75
79
|
#
|
@@ -107,11 +111,18 @@ module ActiveRecord
|
|
107
111
|
end
|
108
112
|
|
109
113
|
if touch
|
110
|
-
|
114
|
+
names = touch if touch != true
|
115
|
+
touch_updates = touch_attributes_with_time(*names)
|
111
116
|
updates << sanitize_sql_for_assignment(touch_updates) unless touch_updates.empty?
|
112
117
|
end
|
113
118
|
|
114
|
-
|
119
|
+
if id.is_a?(Relation) && self == id.klass
|
120
|
+
relation = id
|
121
|
+
else
|
122
|
+
relation = unscoped.where!(primary_key => id)
|
123
|
+
end
|
124
|
+
|
125
|
+
relation.update_all updates.join(", ")
|
115
126
|
end
|
116
127
|
|
117
128
|
# Increment a numeric field by one, via a direct SQL update.
|
@@ -165,13 +176,6 @@ module ActiveRecord
|
|
165
176
|
def decrement_counter(counter_name, id, touch: nil)
|
166
177
|
update_counters(id, counter_name => -1, touch: touch)
|
167
178
|
end
|
168
|
-
|
169
|
-
private
|
170
|
-
def touch_updates(touch)
|
171
|
-
touch = timestamp_attributes_for_update_in_model if touch == true
|
172
|
-
touch_time = current_time_from_proper_timezone
|
173
|
-
Array(touch).map { |column| [ column, touch_time ] }.to_h
|
174
|
-
end
|
175
179
|
end
|
176
180
|
|
177
181
|
private
|
data/lib/active_record/enum.rb
CHANGED
data/lib/active_record/errors.rb
CHANGED
@@ -117,16 +117,27 @@ module ActiveRecord
|
|
117
117
|
|
118
118
|
# Raised when a foreign key constraint cannot be added because the column type does not match the referenced column type.
|
119
119
|
class MismatchedForeignKey < StatementInvalid
|
120
|
-
def initialize(
|
121
|
-
|
120
|
+
def initialize(
|
121
|
+
adapter = nil,
|
122
|
+
message: nil,
|
123
|
+
sql: nil,
|
124
|
+
binds: nil,
|
125
|
+
table: nil,
|
126
|
+
foreign_key: nil,
|
127
|
+
target_table: nil,
|
128
|
+
primary_key: nil,
|
129
|
+
primary_key_column: nil
|
130
|
+
)
|
122
131
|
if table
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
132
|
+
type = primary_key_column.bigint? ? :bigint : primary_key_column.type
|
133
|
+
msg = <<-EOM.squish
|
134
|
+
Column `#{foreign_key}` on table `#{table}` does not match column `#{primary_key}` on `#{target_table}`,
|
135
|
+
which has type `#{primary_key_column.sql_type}`.
|
136
|
+
To resolve this issue, change the type of the `#{foreign_key}` column on `#{table}` to be :#{type}.
|
137
|
+
(For example `t.#{type} :#{foreign_key}`).
|
127
138
|
EOM
|
128
139
|
else
|
129
|
-
msg = <<-EOM
|
140
|
+
msg = <<-EOM.squish
|
130
141
|
There is a mismatch between the foreign key and primary key column types.
|
131
142
|
Verify that the foreign key column type and the primary key of the associated table match types.
|
132
143
|
EOM
|
@@ -136,11 +147,6 @@ module ActiveRecord
|
|
136
147
|
end
|
137
148
|
super(msg)
|
138
149
|
end
|
139
|
-
|
140
|
-
private
|
141
|
-
def column_type(table, column)
|
142
|
-
@adapter.columns(table).detect { |c| c.name == column }.sql_type
|
143
|
-
end
|
144
150
|
end
|
145
151
|
|
146
152
|
# Raised when a record cannot be inserted or updated because it would violate a not null constraint.
|
@@ -17,20 +17,18 @@ module ActiveRecord
|
|
17
17
|
|
18
18
|
class V5_1 < V5_2
|
19
19
|
def change_column(table_name, column_name, type, options = {})
|
20
|
-
if adapter_name == "PostgreSQL"
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
|
26
|
-
change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
|
20
|
+
if connection.adapter_name == "PostgreSQL"
|
21
|
+
super(table_name, column_name, type, options.except(:default, :null, :comment))
|
22
|
+
connection.change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
|
23
|
+
connection.change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
|
24
|
+
connection.change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
|
27
25
|
else
|
28
26
|
super
|
29
27
|
end
|
30
28
|
end
|
31
29
|
|
32
30
|
def create_table(table_name, options = {})
|
33
|
-
if adapter_name == "Mysql2"
|
31
|
+
if connection.adapter_name == "Mysql2"
|
34
32
|
super(table_name, options: "ENGINE=InnoDB", **options)
|
35
33
|
else
|
36
34
|
super
|
@@ -52,13 +50,13 @@ module ActiveRecord
|
|
52
50
|
end
|
53
51
|
|
54
52
|
def create_table(table_name, options = {})
|
55
|
-
if adapter_name == "PostgreSQL"
|
53
|
+
if connection.adapter_name == "PostgreSQL"
|
56
54
|
if options[:id] == :uuid && !options.key?(:default)
|
57
55
|
options[:default] = "uuid_generate_v4()"
|
58
56
|
end
|
59
57
|
end
|
60
58
|
|
61
|
-
unless adapter_name == "Mysql2" && options[:id] == :bigint
|
59
|
+
unless connection.adapter_name == "Mysql2" && options[:id] == :bigint
|
62
60
|
if [:integer, :bigint].include?(options[:id]) && !options.key?(:default)
|
63
61
|
options[:default] = nil
|
64
62
|
end
|
@@ -175,7 +173,7 @@ module ActiveRecord
|
|
175
173
|
if options[:name].present?
|
176
174
|
options[:name].to_s
|
177
175
|
else
|
178
|
-
index_name(table_name, column: column_names)
|
176
|
+
connection.index_name(table_name, column: column_names)
|
179
177
|
end
|
180
178
|
super
|
181
179
|
end
|
@@ -195,15 +193,17 @@ module ActiveRecord
|
|
195
193
|
end
|
196
194
|
|
197
195
|
def index_name_for_remove(table_name, options = {})
|
198
|
-
index_name = index_name(table_name, options)
|
196
|
+
index_name = connection.index_name(table_name, options)
|
199
197
|
|
200
|
-
unless index_name_exists?(table_name, index_name)
|
198
|
+
unless connection.index_name_exists?(table_name, index_name)
|
201
199
|
if options.is_a?(Hash) && options.has_key?(:name)
|
202
200
|
options_without_column = options.dup
|
203
201
|
options_without_column.delete :column
|
204
|
-
index_name_without_column = index_name(table_name, options_without_column)
|
202
|
+
index_name_without_column = connection.index_name(table_name, options_without_column)
|
205
203
|
|
206
|
-
|
204
|
+
if connection.index_name_exists?(table_name, index_name_without_column)
|
205
|
+
return index_name_without_column
|
206
|
+
end
|
207
207
|
end
|
208
208
|
|
209
209
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
|
@@ -1163,7 +1163,7 @@ module ActiveRecord
|
|
1163
1163
|
|
1164
1164
|
def migrations_path=(path)
|
1165
1165
|
ActiveSupport::Deprecation.warn \
|
1166
|
-
"ActiveRecord::Migrator.
|
1166
|
+
"`ActiveRecord::Migrator.migrations_path=` is now deprecated and will be removed in Rails 6.0. " \
|
1167
1167
|
"You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
|
1168
1168
|
self.migrations_paths = [path]
|
1169
1169
|
end
|
@@ -375,7 +375,7 @@ module ActiveRecord
|
|
375
375
|
# default values when instantiating the Active Record object for this table.
|
376
376
|
def column_defaults
|
377
377
|
load_schema
|
378
|
-
@column_defaults ||= _default_attributes.to_hash
|
378
|
+
@column_defaults ||= _default_attributes.deep_dup.to_hash
|
379
379
|
end
|
380
380
|
|
381
381
|
def _default_attributes # :nodoc:
|
@@ -373,7 +373,7 @@ module ActiveRecord
|
|
373
373
|
became = klass.allocate
|
374
374
|
became.send(:initialize)
|
375
375
|
became.instance_variable_set("@attributes", @attributes)
|
376
|
-
became.instance_variable_set("@mutations_from_database", @mutations_from_database
|
376
|
+
became.instance_variable_set("@mutations_from_database", @mutations_from_database ||= nil)
|
377
377
|
became.instance_variable_set("@changed_attributes", attributes_changed_by_setter)
|
378
378
|
became.instance_variable_set("@new_record", new_record?)
|
379
379
|
became.instance_variable_set("@destroyed", destroyed?)
|
@@ -473,15 +473,16 @@ module ActiveRecord
|
|
473
473
|
verify_readonly_attribute(key.to_s)
|
474
474
|
end
|
475
475
|
|
476
|
+
id_in_database = self.id_in_database
|
477
|
+
attributes.each do |k, v|
|
478
|
+
write_attribute_without_type_cast(k, v)
|
479
|
+
end
|
480
|
+
|
476
481
|
affected_rows = self.class._update_record(
|
477
482
|
attributes,
|
478
483
|
self.class.primary_key => id_in_database
|
479
484
|
)
|
480
485
|
|
481
|
-
attributes.each do |k, v|
|
482
|
-
write_attribute_without_type_cast(k, v)
|
483
|
-
end
|
484
|
-
|
485
486
|
affected_rows == 1
|
486
487
|
end
|
487
488
|
|
@@ -26,19 +26,12 @@ module ActiveRecord
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.run
|
29
|
-
ActiveRecord::Base.connection_handler.connection_pool_list.
|
30
|
-
|
31
|
-
|
32
|
-
pool.enable_query_cache!
|
33
|
-
|
34
|
-
[pool, caching_was_enabled]
|
35
|
-
end
|
29
|
+
ActiveRecord::Base.connection_handler.connection_pool_list.
|
30
|
+
reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! }
|
36
31
|
end
|
37
32
|
|
38
|
-
def self.complete(
|
39
|
-
|
40
|
-
pool.disable_query_cache! unless caching_was_enabled
|
41
|
-
end
|
33
|
+
def self.complete(pools)
|
34
|
+
pools.each { |pool| pool.disable_query_cache! }
|
42
35
|
|
43
36
|
ActiveRecord::Base.connection_handler.connection_pool_list.each do |pool|
|
44
37
|
pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
|
@@ -40,7 +40,7 @@ module ActiveRecord
|
|
40
40
|
def find_by_sql(sql, binds = [], preparable: nil, &block)
|
41
41
|
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
|
42
42
|
column_types = result_set.column_types.dup
|
43
|
-
|
43
|
+
attribute_types.each_key { |k| column_types.delete k }
|
44
44
|
message_bus = ActiveSupport::Notifications.instrumenter
|
45
45
|
|
46
46
|
payload = {
|
@@ -169,9 +169,7 @@ end_warning
|
|
169
169
|
end
|
170
170
|
|
171
171
|
initializer "active_record.set_executor_hooks" do
|
172
|
-
|
173
|
-
ActiveRecord::QueryCache.install_executor_hooks
|
174
|
-
end
|
172
|
+
ActiveRecord::QueryCache.install_executor_hooks
|
175
173
|
end
|
176
174
|
|
177
175
|
initializer "active_record.add_watchable_files" do |app|
|
@@ -224,5 +222,23 @@ MSG
|
|
224
222
|
end
|
225
223
|
end
|
226
224
|
end
|
225
|
+
|
226
|
+
initializer "active_record.use_yaml_unsafe_load" do |app|
|
227
|
+
config.after_initialize do
|
228
|
+
unless app.config.active_record.use_yaml_unsafe_load.nil?
|
229
|
+
ActiveRecord::Base.use_yaml_unsafe_load =
|
230
|
+
app.config.active_record.use_yaml_unsafe_load
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
initializer "active_record.yaml_column_permitted_classes" do |app|
|
236
|
+
config.after_initialize do
|
237
|
+
unless app.config.active_record.yaml_column_permitted_classes.nil?
|
238
|
+
ActiveRecord::Base.yaml_column_permitted_classes =
|
239
|
+
app.config.active_record.yaml_column_permitted_classes
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
227
243
|
end
|
228
244
|
end
|