activerecord 5.2.5 → 6.0.0.beta1
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 +299 -748
- data/MIT-LICENSE +3 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +2 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations.rb +16 -12
- data/lib/active_record/associations/association.rb +35 -19
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/belongs_to.rb +14 -50
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/collection_association.rb +11 -25
- data/lib/active_record/associations/collection_proxy.rb +32 -6
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +25 -18
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +15 -20
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +32 -29
- data/lib/active_record/associations/preloader/association.rb +1 -2
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods.rb +34 -56
- data/lib/active_record/attribute_methods/dirty.rb +64 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -7
- data/lib/active_record/attribute_methods/read.rb +16 -48
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +15 -16
- data/lib/active_record/autosave_association.rb +7 -21
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +3 -17
- data/lib/active_record/collection_cache_key.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
- data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
- data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
- data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
- data/lib/active_record/connection_handling.rb +132 -26
- data/lib/active_record/core.rb +76 -43
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations.rb +184 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +74 -0
- data/lib/active_record/enum.rb +22 -7
- data/lib/active_record/errors.rb +24 -21
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +140 -472
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +12 -2
- data/lib/active_record/integration.rb +56 -16
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/migration.rb +38 -37
- data/lib/active_record/migration/command_recorder.rb +35 -5
- data/lib/active_record/migration/compatibility.rb +34 -16
- data/lib/active_record/model_schema.rb +30 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +18 -7
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +19 -11
- data/lib/active_record/railtie.rb +71 -42
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +94 -43
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +38 -28
- data/lib/active_record/relation/delegation.rb +4 -13
- data/lib/active_record/relation/finder_methods.rb +12 -25
- data/lib/active_record/relation/merger.rb +2 -6
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/query_attribute.rb +15 -12
- data/lib/active_record/relation/query_methods.rb +29 -52
- data/lib/active_record/relation/where_clause.rb +4 -0
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +2 -39
- data/lib/active_record/schema.rb +1 -10
- data/lib/active_record/schema_dumper.rb +12 -6
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +10 -3
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +39 -8
- data/lib/active_record/table_metadata.rb +1 -4
- data/lib/active_record/tasks/database_tasks.rb +89 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +38 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/transactions.rb +3 -22
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type_caster/connection.rb +1 -6
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +13 -25
- data/lib/arel.rb +44 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +67 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +63 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values.rb +16 -0
- data/lib/arel/nodes/values_list.rb +24 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +199 -0
- data/lib/arel/visitors/dot.rb +292 -0
- data/lib/arel/visitors/ibm_db.rb +21 -0
- data/lib/arel/visitors/informix.rb +56 -0
- data/lib/arel/visitors/mssql.rb +143 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +67 -0
- data/lib/arel/visitors/postgresql.rb +116 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +913 -0
- data/lib/arel/visitors/visitor.rb +42 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- metadata +104 -26
@@ -32,17 +32,17 @@ module ActiveRecord
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def enable_query_cache!
|
35
|
-
@query_cache_enabled[connection_cache_key(
|
35
|
+
@query_cache_enabled[connection_cache_key(Thread.current)] = true
|
36
36
|
connection.enable_query_cache! if active_connection?
|
37
37
|
end
|
38
38
|
|
39
39
|
def disable_query_cache!
|
40
|
-
@query_cache_enabled.delete connection_cache_key(
|
40
|
+
@query_cache_enabled.delete connection_cache_key(Thread.current)
|
41
41
|
connection.disable_query_cache! if active_connection?
|
42
42
|
end
|
43
43
|
|
44
44
|
def query_cache_enabled
|
45
|
-
@query_cache_enabled[connection_cache_key(
|
45
|
+
@query_cache_enabled[connection_cache_key(Thread.current)]
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -96,11 +96,6 @@ module ActiveRecord
|
|
96
96
|
if @query_cache_enabled && !locked?(arel)
|
97
97
|
arel = arel_from_relation(arel)
|
98
98
|
sql, binds = to_sql_and_binds(arel, binds)
|
99
|
-
|
100
|
-
if preparable.nil?
|
101
|
-
preparable = prepared_statements ? visitor.preparable : false
|
102
|
-
end
|
103
|
-
|
104
99
|
cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable) }
|
105
100
|
else
|
106
101
|
super
|
@@ -115,12 +110,7 @@ module ActiveRecord
|
|
115
110
|
if @query_cache[sql].key?(binds)
|
116
111
|
ActiveSupport::Notifications.instrument(
|
117
112
|
"sql.active_record",
|
118
|
-
sql
|
119
|
-
binds: binds,
|
120
|
-
type_casted_binds: -> { type_casted_binds(binds) },
|
121
|
-
name: name,
|
122
|
-
connection_id: object_id,
|
123
|
-
cached: true,
|
113
|
+
cache_notification_info(sql, name, binds)
|
124
114
|
)
|
125
115
|
@query_cache[sql][binds]
|
126
116
|
else
|
@@ -130,6 +120,19 @@ module ActiveRecord
|
|
130
120
|
end
|
131
121
|
end
|
132
122
|
|
123
|
+
# Database adapters can override this method to
|
124
|
+
# provide custom cache information.
|
125
|
+
def cache_notification_info(sql, name, binds)
|
126
|
+
{
|
127
|
+
sql: sql,
|
128
|
+
binds: binds,
|
129
|
+
type_casted_binds: -> { type_casted_binds(binds) },
|
130
|
+
name: name,
|
131
|
+
connection_id: object_id,
|
132
|
+
cached: true
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
133
136
|
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
|
134
137
|
# queries should not be cached.
|
135
138
|
def locked?(arel)
|
@@ -60,7 +60,7 @@ module ActiveRecord
|
|
60
60
|
# Quotes a string, escaping any ' (single quote) and \ (backslash)
|
61
61
|
# characters.
|
62
62
|
def quote_string(s)
|
63
|
-
s.gsub('\\'
|
63
|
+
s.gsub('\\', '\&\&').gsub("'", "''") # ' (for ruby-mode)
|
64
64
|
end
|
65
65
|
|
66
66
|
# Quotes the column name. Defaults to no quoting.
|
@@ -95,7 +95,7 @@ module ActiveRecord
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def quoted_true
|
98
|
-
"TRUE"
|
98
|
+
"TRUE"
|
99
99
|
end
|
100
100
|
|
101
101
|
def unquoted_true
|
@@ -103,7 +103,7 @@ module ActiveRecord
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def quoted_false
|
106
|
-
"FALSE"
|
106
|
+
"FALSE"
|
107
107
|
end
|
108
108
|
|
109
109
|
def unquoted_false
|
@@ -157,13 +157,9 @@ module ActiveRecord
|
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
-
def types_which_need_no_typecasting
|
161
|
-
[nil, Numeric, String]
|
162
|
-
end
|
163
|
-
|
164
160
|
def _quote(value)
|
165
161
|
case value
|
166
|
-
when String, ActiveSupport::Multibyte::Chars
|
162
|
+
when String, Symbol, ActiveSupport::Multibyte::Chars
|
167
163
|
"'#{quote_string(value.to_s)}'"
|
168
164
|
when true then quoted_true
|
169
165
|
when false then quoted_false
|
@@ -174,7 +170,6 @@ module ActiveRecord
|
|
174
170
|
when Type::Binary::Data then quoted_binary(value)
|
175
171
|
when Type::Time::Value then "'#{quoted_time(value)}'"
|
176
172
|
when Date, Time then "'#{quoted_date(value)}'"
|
177
|
-
when Symbol then "'#{quote_string(value.to_s)}'"
|
178
173
|
when Class then "'#{value}'"
|
179
174
|
else raise TypeError, "can't quote #{value.class.name}"
|
180
175
|
end
|
@@ -188,10 +183,9 @@ module ActiveRecord
|
|
188
183
|
when false then unquoted_false
|
189
184
|
# BigDecimals need to be put in a non-normalized form and quoted.
|
190
185
|
when BigDecimal then value.to_s("F")
|
186
|
+
when nil, Numeric, String then value
|
191
187
|
when Type::Time::Value then quoted_time(value)
|
192
188
|
when Date, Time then quoted_date(value)
|
193
|
-
when *types_which_need_no_typecasting
|
194
|
-
value
|
195
189
|
else raise TypeError
|
196
190
|
end
|
197
191
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/string/strip"
|
4
|
-
|
5
3
|
module ActiveRecord
|
6
4
|
module ConnectionAdapters
|
7
5
|
class AbstractAdapter
|
@@ -17,14 +15,13 @@ module ActiveRecord
|
|
17
15
|
end
|
18
16
|
|
19
17
|
delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
|
20
|
-
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options,
|
21
|
-
|
22
|
-
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options
|
18
|
+
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options,
|
19
|
+
to: :@conn, private: true
|
23
20
|
|
24
21
|
private
|
25
22
|
|
26
23
|
def visit_AlterTable(o)
|
27
|
-
sql = "ALTER TABLE #{quote_table_name(o.name)} "
|
24
|
+
sql = +"ALTER TABLE #{quote_table_name(o.name)} "
|
28
25
|
sql << o.adds.map { |col| accept col }.join(" ")
|
29
26
|
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
|
30
27
|
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
|
@@ -32,17 +29,19 @@ module ActiveRecord
|
|
32
29
|
|
33
30
|
def visit_ColumnDefinition(o)
|
34
31
|
o.sql_type = type_to_sql(o.type, o.options)
|
35
|
-
column_sql = "#{quote_column_name(o.name)} #{o.sql_type}"
|
32
|
+
column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
|
36
33
|
add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
|
37
34
|
column_sql
|
38
35
|
end
|
39
36
|
|
40
37
|
def visit_AddColumnDefinition(o)
|
41
|
-
"ADD #{accept(o.column)}"
|
38
|
+
+"ADD #{accept(o.column)}"
|
42
39
|
end
|
43
40
|
|
44
41
|
def visit_TableDefinition(o)
|
45
|
-
create_sql = "CREATE#{
|
42
|
+
create_sql = +"CREATE#{table_modifier_in_create(o)} TABLE "
|
43
|
+
create_sql << "IF NOT EXISTS " if o.if_not_exists
|
44
|
+
create_sql << "#{quote_table_name(o.name)} "
|
46
45
|
|
47
46
|
statements = o.columns.map { |c| accept c }
|
48
47
|
statements << accept(o.primary_keys) if o.primary_keys
|
@@ -66,7 +65,7 @@ module ActiveRecord
|
|
66
65
|
end
|
67
66
|
|
68
67
|
def visit_ForeignKeyDefinition(o)
|
69
|
-
sql =
|
68
|
+
sql = +<<~SQL
|
70
69
|
CONSTRAINT #{quote_column_name(o.name)}
|
71
70
|
FOREIGN KEY (#{quote_column_name(o.column)})
|
72
71
|
REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
|
@@ -122,6 +121,11 @@ module ActiveRecord
|
|
122
121
|
sql
|
123
122
|
end
|
124
123
|
|
124
|
+
# Returns any SQL string to go between CREATE and TABLE. May be nil.
|
125
|
+
def table_modifier_in_create(o)
|
126
|
+
" TEMPORARY" if o.temporary
|
127
|
+
end
|
128
|
+
|
125
129
|
def foreign_key_in_create(from_table, to_table, options)
|
126
130
|
options = foreign_key_options(from_table, to_table, options)
|
127
131
|
accept ForeignKeyDefinition.new(from_table, to_table, options)
|
@@ -133,7 +137,7 @@ module ActiveRecord
|
|
133
137
|
when :cascade then "ON #{action} CASCADE"
|
134
138
|
when :restrict then "ON #{action} RESTRICT"
|
135
139
|
else
|
136
|
-
raise ArgumentError,
|
140
|
+
raise ArgumentError, <<~MSG
|
137
141
|
'#{dependency}' is not supported for :on_update or :on_delete.
|
138
142
|
Supported values are: :nullify, :cascade, :restrict
|
139
143
|
MSG
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/deprecation"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters #:nodoc:
|
5
7
|
# Abstract representation of an index definition on a table. Instances of
|
@@ -101,6 +103,10 @@ module ActiveRecord
|
|
101
103
|
end
|
102
104
|
alias validated? validate?
|
103
105
|
|
106
|
+
def export_name_on_schema_dump?
|
107
|
+
name !~ ActiveRecord::SchemaDumper.fk_ignore_pattern
|
108
|
+
end
|
109
|
+
|
104
110
|
def defined_for?(to_table_ord = nil, to_table: nil, **options)
|
105
111
|
if to_table_ord
|
106
112
|
self.to_table == to_table_ord.to_s
|
@@ -151,13 +157,8 @@ module ActiveRecord
|
|
151
157
|
end
|
152
158
|
end
|
153
159
|
|
154
|
-
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
155
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
156
|
-
protected
|
157
|
-
|
158
|
-
attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
|
159
|
-
|
160
160
|
private
|
161
|
+
attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
|
161
162
|
|
162
163
|
def as_options(value)
|
163
164
|
value.is_a?(Hash) ? value : {}
|
@@ -257,15 +258,25 @@ module ActiveRecord
|
|
257
258
|
class TableDefinition
|
258
259
|
include ColumnMethods
|
259
260
|
|
260
|
-
|
261
|
-
|
261
|
+
attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys
|
262
|
+
attr_writer :indexes
|
263
|
+
deprecate :indexes=
|
262
264
|
|
263
|
-
def initialize(
|
265
|
+
def initialize(
|
266
|
+
name,
|
267
|
+
temporary: false,
|
268
|
+
if_not_exists: false,
|
269
|
+
options: nil,
|
270
|
+
as: nil,
|
271
|
+
comment: nil,
|
272
|
+
**
|
273
|
+
)
|
264
274
|
@columns_hash = {}
|
265
275
|
@indexes = []
|
266
276
|
@foreign_keys = []
|
267
277
|
@primary_keys = nil
|
268
278
|
@temporary = temporary
|
279
|
+
@if_not_exists = if_not_exists
|
269
280
|
@options = options
|
270
281
|
@as = as
|
271
282
|
@name = name
|
@@ -349,16 +360,20 @@ module ActiveRecord
|
|
349
360
|
#
|
350
361
|
# create_table :taggings do |t|
|
351
362
|
# t.references :tag, index: { name: 'index_taggings_on_tag_id' }
|
352
|
-
# t.references :tagger, polymorphic: true
|
353
|
-
# t.references :taggable, polymorphic: { default: 'Photo' }
|
363
|
+
# t.references :tagger, polymorphic: true
|
364
|
+
# t.references :taggable, polymorphic: { default: 'Photo' }, index: false
|
354
365
|
# end
|
355
366
|
def column(name, type, options = {})
|
356
367
|
name = name.to_s
|
357
368
|
type = type.to_sym if type
|
358
369
|
options = options.dup
|
359
370
|
|
360
|
-
if @columns_hash[name]
|
361
|
-
|
371
|
+
if @columns_hash[name]
|
372
|
+
if @columns_hash[name].primary_key?
|
373
|
+
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
374
|
+
else
|
375
|
+
raise ArgumentError, "you can't define an already defined column '#{name}'."
|
376
|
+
end
|
362
377
|
end
|
363
378
|
|
364
379
|
index_options = options.delete(:index)
|
@@ -524,7 +539,9 @@ module ActiveRecord
|
|
524
539
|
#
|
525
540
|
# See TableDefinition#column for details of the options you can use.
|
526
541
|
def column(column_name, type, options = {})
|
542
|
+
index_options = options.delete(:index)
|
527
543
|
@base.add_column(name, column_name, type, options)
|
544
|
+
index(column_name, index_options.is_a?(Hash) ? index_options : {}) if index_options
|
528
545
|
end
|
529
546
|
|
530
547
|
# Checks to see if a column exists.
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "active_record/migration/join_table"
|
4
4
|
require "active_support/core_ext/string/access"
|
5
|
+
require "active_support/deprecation"
|
5
6
|
require "digest/sha2"
|
6
7
|
|
7
8
|
module ActiveRecord
|
@@ -100,7 +101,7 @@ module ActiveRecord
|
|
100
101
|
def index_exists?(table_name, column_name, options = {})
|
101
102
|
column_names = Array(column_name).map(&:to_s)
|
102
103
|
checks = []
|
103
|
-
checks << lambda { |i|
|
104
|
+
checks << lambda { |i| i.columns == column_names }
|
104
105
|
checks << lambda { |i| i.unique } if options[:unique]
|
105
106
|
checks << lambda { |i| i.name == options[:name].to_s } if options[:name]
|
106
107
|
|
@@ -205,19 +206,22 @@ module ActiveRecord
|
|
205
206
|
# Set to true to drop the table before creating it.
|
206
207
|
# Set to +:cascade+ to drop dependent objects as well.
|
207
208
|
# Defaults to false.
|
209
|
+
# [<tt>:if_not_exists</tt>]
|
210
|
+
# Set to true to avoid raising an error when the table already exists.
|
211
|
+
# Defaults to false.
|
208
212
|
# [<tt>:as</tt>]
|
209
213
|
# SQL to use to generate the table. When this option is used, the block is
|
210
214
|
# ignored, as are the <tt>:id</tt> and <tt>:primary_key</tt> options.
|
211
215
|
#
|
212
216
|
# ====== Add a backend specific option to the generated SQL (MySQL)
|
213
217
|
#
|
214
|
-
# create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=
|
218
|
+
# create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4')
|
215
219
|
#
|
216
220
|
# generates:
|
217
221
|
#
|
218
222
|
# CREATE TABLE suppliers (
|
219
223
|
# id bigint auto_increment PRIMARY KEY
|
220
|
-
# ) ENGINE=InnoDB DEFAULT CHARSET=
|
224
|
+
# ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
221
225
|
#
|
222
226
|
# ====== Rename the primary key column
|
223
227
|
#
|
@@ -287,8 +291,8 @@ module ActiveRecord
|
|
287
291
|
# SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
|
288
292
|
#
|
289
293
|
# See also TableDefinition#column for details on how to create columns.
|
290
|
-
def create_table(table_name,
|
291
|
-
td = create_table_definition
|
294
|
+
def create_table(table_name, **options)
|
295
|
+
td = create_table_definition(table_name, options)
|
292
296
|
|
293
297
|
if options[:id] != false && !options[:as]
|
294
298
|
pk = options.fetch(:primary_key) do
|
@@ -317,7 +321,9 @@ module ActiveRecord
|
|
317
321
|
end
|
318
322
|
|
319
323
|
if supports_comments? && !supports_comments_in_create?
|
320
|
-
|
324
|
+
if table_comment = options[:comment].presence
|
325
|
+
change_table_comment(table_name, table_comment)
|
326
|
+
end
|
321
327
|
|
322
328
|
td.columns.each do |column|
|
323
329
|
change_column_comment(table_name, column.name, column.comment) if column.comment.present?
|
@@ -522,6 +528,9 @@ module ActiveRecord
|
|
522
528
|
# Specifies the precision for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
|
523
529
|
# * <tt>:scale</tt> -
|
524
530
|
# Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
|
531
|
+
# * <tt>:collation</tt> -
|
532
|
+
# Specifies the collation for a <tt>:string</tt> or <tt>:text</tt> column. If not specified, the
|
533
|
+
# column will have the same collation as the table.
|
525
534
|
# * <tt>:comment</tt> -
|
526
535
|
# Specifies the comment for the column. This option is ignored by some backends.
|
527
536
|
#
|
@@ -599,6 +608,7 @@ module ActiveRecord
|
|
599
608
|
# The +type+ and +options+ parameters will be ignored if present. It can be helpful
|
600
609
|
# to provide these in a migration's +change+ method so it can be reverted.
|
601
610
|
# In that case, +type+ and +options+ will be used by #add_column.
|
611
|
+
# Indexes on the column are automatically removed.
|
602
612
|
def remove_column(table_name, column_name, type = nil, options = {})
|
603
613
|
execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, options)}"
|
604
614
|
end
|
@@ -842,17 +852,17 @@ module ActiveRecord
|
|
842
852
|
# [<tt>:null</tt>]
|
843
853
|
# Whether the column allows nulls. Defaults to true.
|
844
854
|
#
|
845
|
-
# ====== Create a user_id bigint column
|
855
|
+
# ====== Create a user_id bigint column without a index
|
846
856
|
#
|
847
|
-
# add_reference(:products, :user)
|
857
|
+
# add_reference(:products, :user, index: false)
|
848
858
|
#
|
849
859
|
# ====== Create a user_id string column
|
850
860
|
#
|
851
861
|
# add_reference(:products, :user, type: :string)
|
852
862
|
#
|
853
|
-
# ====== Create supplier_id, supplier_type columns
|
863
|
+
# ====== Create supplier_id, supplier_type columns
|
854
864
|
#
|
855
|
-
# add_reference(:products, :supplier, polymorphic: true
|
865
|
+
# add_reference(:products, :supplier, polymorphic: true)
|
856
866
|
#
|
857
867
|
# ====== Create a supplier_id column with a unique index
|
858
868
|
#
|
@@ -880,7 +890,7 @@ module ActiveRecord
|
|
880
890
|
#
|
881
891
|
# ====== Remove the reference
|
882
892
|
#
|
883
|
-
# remove_reference(:products, :user, index:
|
893
|
+
# remove_reference(:products, :user, index: false)
|
884
894
|
#
|
885
895
|
# ====== Remove polymorphic reference
|
886
896
|
#
|
@@ -888,7 +898,7 @@ module ActiveRecord
|
|
888
898
|
#
|
889
899
|
# ====== Remove the reference with a foreign key
|
890
900
|
#
|
891
|
-
# remove_reference(:products, :user,
|
901
|
+
# remove_reference(:products, :user, foreign_key: true)
|
892
902
|
#
|
893
903
|
def remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options)
|
894
904
|
if foreign_key
|
@@ -980,11 +990,18 @@ module ActiveRecord
|
|
980
990
|
#
|
981
991
|
# remove_foreign_key :accounts, column: :owner_id
|
982
992
|
#
|
993
|
+
# Removes the foreign key on +accounts.owner_id+.
|
994
|
+
#
|
995
|
+
# remove_foreign_key :accounts, to_table: :owners
|
996
|
+
#
|
983
997
|
# Removes the foreign key named +special_fk_name+ on the +accounts+ table.
|
984
998
|
#
|
985
999
|
# remove_foreign_key :accounts, name: :special_fk_name
|
986
1000
|
#
|
987
|
-
# The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key
|
1001
|
+
# The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key
|
1002
|
+
# with an addition of
|
1003
|
+
# [<tt>:to_table</tt>]
|
1004
|
+
# The name of the table that contains the referenced primary key.
|
988
1005
|
def remove_foreign_key(from_table, options_or_to_table = {})
|
989
1006
|
return unless supports_foreign_keys?
|
990
1007
|
|
@@ -1034,15 +1051,18 @@ module ActiveRecord
|
|
1034
1051
|
{ primary_key: true }
|
1035
1052
|
end
|
1036
1053
|
|
1037
|
-
def assume_migrated_upto_version(version, migrations_paths)
|
1038
|
-
|
1054
|
+
def assume_migrated_upto_version(version, migrations_paths = nil)
|
1055
|
+
unless migrations_paths.nil?
|
1056
|
+
ActiveSupport::Deprecation.warn(<<~MSG)
|
1057
|
+
Passing migrations_paths to #assume_migrated_upto_version is deprecated and will be removed in Rails 6.1.
|
1058
|
+
MSG
|
1059
|
+
end
|
1060
|
+
|
1039
1061
|
version = version.to_i
|
1040
1062
|
sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
|
1041
1063
|
|
1042
|
-
migrated =
|
1043
|
-
versions = migration_context.
|
1044
|
-
migration_context.parse_migration_filename(file).first.to_i
|
1045
|
-
end
|
1064
|
+
migrated = migration_context.get_all_versions
|
1065
|
+
versions = migration_context.migrations.map(&:version)
|
1046
1066
|
|
1047
1067
|
unless migrated.include?(version)
|
1048
1068
|
execute "INSERT INTO #{sm_table} (version) VALUES (#{quote(version)})"
|
@@ -1053,13 +1073,7 @@ module ActiveRecord
|
|
1053
1073
|
if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
|
1054
1074
|
raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
|
1055
1075
|
end
|
1056
|
-
|
1057
|
-
execute insert_versions_sql(inserting)
|
1058
|
-
else
|
1059
|
-
inserting.each do |v|
|
1060
|
-
execute insert_versions_sql(v)
|
1061
|
-
end
|
1062
|
-
end
|
1076
|
+
execute insert_versions_sql(inserting)
|
1063
1077
|
end
|
1064
1078
|
end
|
1065
1079
|
|
@@ -1375,7 +1389,7 @@ module ActiveRecord
|
|
1375
1389
|
sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
|
1376
1390
|
|
1377
1391
|
if versions.is_a?(Array)
|
1378
|
-
sql = "INSERT INTO #{sm_table} (version) VALUES\n"
|
1392
|
+
sql = +"INSERT INTO #{sm_table} (version) VALUES\n"
|
1379
1393
|
sql << versions.map { |v| "(#{quote(v)})" }.join(",\n")
|
1380
1394
|
sql << ";\n\n"
|
1381
1395
|
sql
|