activerecord 5.0.7 → 5.1.7
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +657 -2080
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations/alias_tracker.rb +10 -11
- data/lib/active_record/associations/association.rb +23 -5
- data/lib/active_record/associations/association_scope.rb +95 -81
- data/lib/active_record/associations/belongs_to_association.rb +7 -4
- data/lib/active_record/associations/builder/belongs_to.rb +30 -16
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +36 -205
- data/lib/active_record/associations/collection_proxy.rb +132 -63
- data/lib/active_record/associations/has_many_association.rb +10 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -4
- data/lib/active_record/associations/has_one_association.rb +24 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +4 -28
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +121 -118
- data/lib/active_record/associations/preloader/association.rb +64 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +41 -41
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +2 -5
- data/lib/active_record/associations.rb +1591 -1562
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +229 -46
- data/lib/active_record/attribute_methods/primary_key.rb +74 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +30 -33
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_mutation_tracker.rb +63 -11
- data/lib/active_record/attribute_set/builder.rb +27 -33
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attributes.rb +22 -22
- data/lib/active_record/autosave_association.rb +18 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +56 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +3 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +330 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +39 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -51
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +10 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +74 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/abstract/transaction.rb +49 -43
- data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -135
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +404 -424
- data/lib/active_record/connection_adapters/column.rb +26 -4
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -28
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +7 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +23 -27
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +32 -53
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +0 -10
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +32 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -35
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +182 -222
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +6 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +198 -167
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +184 -167
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +109 -93
- data/lib/active_record/counter_cache.rb +60 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +64 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +69 -74
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +23 -28
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +100 -47
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/migration.rb +153 -155
- data/lib/active_record/model_schema.rb +94 -107
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +11 -34
- data/lib/active_record/persistence.rb +65 -50
- data/lib/active_record/query_cache.rb +2 -6
- data/lib/active_record/querying.rb +3 -4
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +105 -133
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +154 -108
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/batches.rb +80 -51
- data/lib/active_record/relation/calculations.rb +169 -162
- data/lib/active_record/relation/delegation.rb +32 -31
- data/lib/active_record/relation/finder_methods.rb +197 -231
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +255 -293
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +80 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/relation.rb +93 -119
- data/lib/active_record/result.rb +41 -32
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +176 -192
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +15 -38
- data/lib/active_record/schema_migration.rb +8 -4
- data/lib/active_record/scoping/default.rb +90 -90
- data/lib/active_record/scoping/named.rb +11 -11
- data/lib/active_record/scoping.rb +6 -6
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +65 -55
- data/lib/active_record/tasks/mysql_database_tasks.rb +76 -73
- data/lib/active_record/tasks/postgresql_database_tasks.rb +72 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +46 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +97 -109
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +13 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/internal/abstract_json.rb +4 -0
- data/lib/active_record/type/serialized.rb +14 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +20 -20
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/migration.rb +1 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- data/lib/rails/generators/active_record.rb +4 -4
- metadata +24 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "active_record/migration/join_table"
|
2
|
+
require "active_support/core_ext/string/access"
|
3
|
+
require "digest"
|
4
4
|
|
5
5
|
module ActiveRecord
|
6
6
|
module ConnectionAdapters # :nodoc:
|
@@ -25,12 +25,14 @@ module ActiveRecord
|
|
25
25
|
|
26
26
|
# Truncates a table alias according to the limits of the current adapter.
|
27
27
|
def table_alias_for(table_name)
|
28
|
-
table_name[0...table_alias_length].tr(
|
28
|
+
table_name[0...table_alias_length].tr(".", "_")
|
29
29
|
end
|
30
30
|
|
31
31
|
# Returns the relation names useable to back Active Record models.
|
32
32
|
# For most adapters this means all #tables and #views.
|
33
33
|
def data_sources
|
34
|
+
query_values(data_source_sql, "SCHEMA")
|
35
|
+
rescue NotImplementedError
|
34
36
|
tables | views
|
35
37
|
end
|
36
38
|
|
@@ -39,12 +41,14 @@ module ActiveRecord
|
|
39
41
|
# data_source_exists?(:ebooks)
|
40
42
|
#
|
41
43
|
def data_source_exists?(name)
|
44
|
+
query_values(data_source_sql(name), "SCHEMA").any? if name.present?
|
45
|
+
rescue NotImplementedError
|
42
46
|
data_sources.include?(name.to_s)
|
43
47
|
end
|
44
48
|
|
45
49
|
# Returns an array of table names defined in the database.
|
46
|
-
def tables
|
47
|
-
|
50
|
+
def tables
|
51
|
+
query_values(data_source_sql(type: "BASE TABLE"), "SCHEMA")
|
48
52
|
end
|
49
53
|
|
50
54
|
# Checks to see if the table +table_name+ exists on the database.
|
@@ -52,12 +56,14 @@ module ActiveRecord
|
|
52
56
|
# table_exists?(:developers)
|
53
57
|
#
|
54
58
|
def table_exists?(table_name)
|
59
|
+
query_values(data_source_sql(table_name, type: "BASE TABLE"), "SCHEMA").any? if table_name.present?
|
60
|
+
rescue NotImplementedError
|
55
61
|
tables.include?(table_name.to_s)
|
56
62
|
end
|
57
63
|
|
58
64
|
# Returns an array of view names defined in the database.
|
59
65
|
def views
|
60
|
-
|
66
|
+
query_values(data_source_sql(type: "VIEW"), "SCHEMA")
|
61
67
|
end
|
62
68
|
|
63
69
|
# Checks to see if the view +view_name+ exists on the database.
|
@@ -65,11 +71,15 @@ module ActiveRecord
|
|
65
71
|
# view_exists?(:ebooks)
|
66
72
|
#
|
67
73
|
def view_exists?(view_name)
|
74
|
+
query_values(data_source_sql(view_name, type: "VIEW"), "SCHEMA").any? if view_name.present?
|
75
|
+
rescue NotImplementedError
|
68
76
|
views.include?(view_name.to_s)
|
69
77
|
end
|
70
78
|
|
71
79
|
# Returns an array of indexes for the given table.
|
72
|
-
|
80
|
+
def indexes(table_name, name = nil)
|
81
|
+
raise NotImplementedError, "#indexes is not implemented"
|
82
|
+
end
|
73
83
|
|
74
84
|
# Checks to see if an index exists on a table for a given index definition.
|
75
85
|
#
|
@@ -120,7 +130,7 @@ module ActiveRecord
|
|
120
130
|
checks = []
|
121
131
|
checks << lambda { |c| c.name == column_name }
|
122
132
|
checks << lambda { |c| c.type == type } if type
|
123
|
-
|
133
|
+
column_options_keys.each do |attr|
|
124
134
|
checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
|
125
135
|
end
|
126
136
|
|
@@ -174,7 +184,7 @@ module ActiveRecord
|
|
174
184
|
# A Symbol can be used to specify the type of the generated primary key column.
|
175
185
|
# [<tt>:primary_key</tt>]
|
176
186
|
# The name of the primary key, if one is to be added automatically.
|
177
|
-
# Defaults to +id+. If <tt>:id</tt> is false this option is ignored.
|
187
|
+
# Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored.
|
178
188
|
#
|
179
189
|
# Note that Active Record models will automatically detect their
|
180
190
|
# primary key. This can be avoided by using
|
@@ -271,8 +281,8 @@ module ActiveRecord
|
|
271
281
|
|
272
282
|
yield td if block_given?
|
273
283
|
|
274
|
-
if options[:force]
|
275
|
-
drop_table(table_name, options)
|
284
|
+
if options[:force]
|
285
|
+
drop_table(table_name, **options, if_exists: true)
|
276
286
|
end
|
277
287
|
|
278
288
|
result = execute schema_creation.accept td
|
@@ -300,9 +310,9 @@ module ActiveRecord
|
|
300
310
|
# # Creates a table called 'assemblies_parts' with no id.
|
301
311
|
# create_join_table(:assemblies, :parts)
|
302
312
|
#
|
303
|
-
# You can pass
|
313
|
+
# You can pass an +options+ hash which can include the following keys:
|
304
314
|
# [<tt>:table_name</tt>]
|
305
|
-
# Sets the table name overriding the default
|
315
|
+
# Sets the table name, overriding the default.
|
306
316
|
# [<tt>:column_options</tt>]
|
307
317
|
# Any extra options you want appended to the columns definition.
|
308
318
|
# [<tt>:options</tt>]
|
@@ -332,18 +342,16 @@ module ActiveRecord
|
|
332
342
|
# part_id int NOT NULL,
|
333
343
|
# ) ENGINE=InnoDB DEFAULT CHARSET=utf8
|
334
344
|
#
|
335
|
-
def create_join_table(table_1, table_2,
|
345
|
+
def create_join_table(table_1, table_2, column_options: {}, **options)
|
336
346
|
join_table_name = find_join_table_name(table_1, table_2, options)
|
337
347
|
|
338
|
-
column_options
|
339
|
-
column_options.reverse_merge!(null: false)
|
340
|
-
type = column_options.delete(:type) || :integer
|
348
|
+
column_options.reverse_merge!(null: false, index: false)
|
341
349
|
|
342
|
-
|
350
|
+
t1_ref, t2_ref = [table_1, table_2].map { |t| t.to_s.singularize }
|
343
351
|
|
344
352
|
create_table(join_table_name, options.merge!(id: false)) do |td|
|
345
|
-
td.
|
346
|
-
td.
|
353
|
+
td.references t1_ref, column_options
|
354
|
+
td.references t2_ref, column_options
|
347
355
|
yield td if block_given?
|
348
356
|
end
|
349
357
|
end
|
@@ -428,7 +436,7 @@ module ActiveRecord
|
|
428
436
|
# t.remove_index :company_id
|
429
437
|
# end
|
430
438
|
#
|
431
|
-
# See also Table for details on all of the various column
|
439
|
+
# See also Table for details on all of the various column transformations.
|
432
440
|
def change_table(table_name, options = {})
|
433
441
|
if supports_bulk_alter? && options[:bulk]
|
434
442
|
recorder = ActiveRecord::Migration::CommandRecorder.new(self)
|
@@ -478,10 +486,10 @@ module ActiveRecord
|
|
478
486
|
#
|
479
487
|
# Available options are (none of these exists by default):
|
480
488
|
# * <tt>:limit</tt> -
|
481
|
-
# Requests a maximum column length. This is number of characters for a <tt>:string</tt> column
|
489
|
+
# Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
|
482
490
|
# and number of bytes for <tt>:text</tt>, <tt>:binary</tt> and <tt>:integer</tt> columns.
|
483
491
|
# * <tt>:default</tt> -
|
484
|
-
# The column's default value. Use nil for NULL
|
492
|
+
# The column's default value. Use +nil+ for +NULL+.
|
485
493
|
# * <tt>:null</tt> -
|
486
494
|
# Allows or disallows +NULL+ values in the column. This option could
|
487
495
|
# have been named <tt>:null_allowed</tt>.
|
@@ -490,7 +498,7 @@ module ActiveRecord
|
|
490
498
|
# * <tt>:scale</tt> -
|
491
499
|
# Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
|
492
500
|
#
|
493
|
-
# Note: The precision is the total number of significant digits
|
501
|
+
# Note: The precision is the total number of significant digits,
|
494
502
|
# and the scale is the number of digits that can be stored following
|
495
503
|
# the decimal point. For example, the number 123.45 has a precision of 5
|
496
504
|
# and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
|
@@ -511,7 +519,7 @@ module ActiveRecord
|
|
511
519
|
# Default is (38,0).
|
512
520
|
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
|
513
521
|
# Default unknown.
|
514
|
-
# * SqlServer
|
522
|
+
# * SqlServer: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
515
523
|
# Default (38,0).
|
516
524
|
#
|
517
525
|
# == Examples
|
@@ -533,6 +541,10 @@ module ActiveRecord
|
|
533
541
|
# add_column(:measurements, :huge_integer, :decimal, precision: 30)
|
534
542
|
# # ALTER TABLE "measurements" ADD "huge_integer" decimal(30)
|
535
543
|
#
|
544
|
+
# # Defines a column that stores an array of a type.
|
545
|
+
# add_column(:users, :skills, :text, array: true)
|
546
|
+
# # ALTER TABLE "users" ADD "skills" text[]
|
547
|
+
#
|
536
548
|
# # Defines a column with a database-specific type.
|
537
549
|
# add_column(:shapes, :triangle, 'polygon')
|
538
550
|
# # ALTER TABLE "shapes" ADD "triangle" polygon
|
@@ -559,7 +571,7 @@ module ActiveRecord
|
|
559
571
|
#
|
560
572
|
# The +type+ and +options+ parameters will be ignored if present. It can be helpful
|
561
573
|
# to provide these in a migration's +change+ method so it can be reverted.
|
562
|
-
# In that case, +type+ and +options+ will be used by add_column.
|
574
|
+
# In that case, +type+ and +options+ will be used by #add_column.
|
563
575
|
def remove_column(table_name, column_name, type = nil, options = {})
|
564
576
|
execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}"
|
565
577
|
end
|
@@ -767,11 +779,12 @@ module ActiveRecord
|
|
767
779
|
end
|
768
780
|
|
769
781
|
# Verifies the existence of an index with a given name.
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
782
|
+
def index_name_exists?(table_name, index_name, default = nil)
|
783
|
+
unless default.nil?
|
784
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
785
|
+
Passing default to #index_name_exists? is deprecated without replacement.
|
786
|
+
MSG
|
787
|
+
end
|
775
788
|
index_name = index_name.to_s
|
776
789
|
indexes(table_name).detect { |i| i.name == index_name }
|
777
790
|
end
|
@@ -822,8 +835,8 @@ module ActiveRecord
|
|
822
835
|
#
|
823
836
|
# add_reference(:products, :supplier, foreign_key: {to_table: :firms})
|
824
837
|
#
|
825
|
-
def add_reference(table_name,
|
826
|
-
ReferenceDefinition.new(
|
838
|
+
def add_reference(table_name, ref_name, **options)
|
839
|
+
ReferenceDefinition.new(ref_name, options).add_to(update_table_definition(table_name, self))
|
827
840
|
end
|
828
841
|
alias :add_belongs_to :add_reference
|
829
842
|
|
@@ -850,6 +863,7 @@ module ActiveRecord
|
|
850
863
|
else
|
851
864
|
foreign_key_options = { to_table: reference_name }
|
852
865
|
end
|
866
|
+
foreign_key_options[:column] ||= "#{ref_name}_id"
|
853
867
|
remove_foreign_key(table_name, **foreign_key_options)
|
854
868
|
end
|
855
869
|
|
@@ -947,13 +961,13 @@ module ActiveRecord
|
|
947
961
|
|
948
962
|
# Checks to see if a foreign key exists on a table for a given foreign key definition.
|
949
963
|
#
|
950
|
-
# #
|
964
|
+
# # Checks to see if a foreign key exists.
|
951
965
|
# foreign_key_exists?(:accounts, :branches)
|
952
966
|
#
|
953
|
-
# #
|
967
|
+
# # Checks to see if a foreign key on a specified column exists.
|
954
968
|
# foreign_key_exists?(:accounts, column: :owner_id)
|
955
969
|
#
|
956
|
-
# #
|
970
|
+
# # Checks to see if a foreign key with a custom name exists.
|
957
971
|
# foreign_key_exists?(:accounts, name: "special_fk_name")
|
958
972
|
#
|
959
973
|
def foreign_key_exists?(from_table, options_or_to_table = {})
|
@@ -962,12 +976,12 @@ module ActiveRecord
|
|
962
976
|
|
963
977
|
def foreign_key_for(from_table, options_or_to_table = {}) # :nodoc:
|
964
978
|
return unless supports_foreign_keys?
|
965
|
-
foreign_keys(from_table).detect {|fk| fk.defined_for? options_or_to_table }
|
979
|
+
foreign_keys(from_table).detect { |fk| fk.defined_for? options_or_to_table }
|
966
980
|
end
|
967
981
|
|
968
982
|
def foreign_key_for!(from_table, options_or_to_table = {}) # :nodoc:
|
969
|
-
foreign_key_for(from_table, options_or_to_table)
|
970
|
-
raise
|
983
|
+
foreign_key_for(from_table, options_or_to_table) || \
|
984
|
+
raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{options_or_to_table}")
|
971
985
|
end
|
972
986
|
|
973
987
|
def foreign_key_column_for(table_name) # :nodoc:
|
@@ -985,12 +999,12 @@ module ActiveRecord
|
|
985
999
|
end
|
986
1000
|
|
987
1001
|
def dump_schema_information #:nodoc:
|
988
|
-
versions = ActiveRecord::SchemaMigration.
|
1002
|
+
versions = ActiveRecord::SchemaMigration.all_versions
|
989
1003
|
insert_versions_sql(versions) if versions.any?
|
990
1004
|
end
|
991
1005
|
|
992
1006
|
def insert_versions_sql(versions) # :nodoc:
|
993
|
-
sm_table = quote_table_name(ActiveRecord::
|
1007
|
+
sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
|
994
1008
|
|
995
1009
|
if versions.is_a?(Array)
|
996
1010
|
sql = "INSERT INTO #{sm_table} (version) VALUES\n"
|
@@ -1002,15 +1016,15 @@ module ActiveRecord
|
|
1002
1016
|
end
|
1003
1017
|
end
|
1004
1018
|
|
1005
|
-
|
1006
|
-
# The migrations module handles this automatically.
|
1007
|
-
def initialize_schema_migrations_table
|
1019
|
+
def initialize_schema_migrations_table # :nodoc:
|
1008
1020
|
ActiveRecord::SchemaMigration.create_table
|
1009
1021
|
end
|
1022
|
+
deprecate :initialize_schema_migrations_table
|
1010
1023
|
|
1011
|
-
def initialize_internal_metadata_table
|
1024
|
+
def initialize_internal_metadata_table # :nodoc:
|
1012
1025
|
ActiveRecord::InternalMetadata.create_table
|
1013
1026
|
end
|
1027
|
+
deprecate :initialize_internal_metadata_table
|
1014
1028
|
|
1015
1029
|
def internal_string_options_for_primary_key # :nodoc:
|
1016
1030
|
{ primary_key: true }
|
@@ -1019,9 +1033,9 @@ module ActiveRecord
|
|
1019
1033
|
def assume_migrated_upto_version(version, migrations_paths)
|
1020
1034
|
migrations_paths = Array(migrations_paths)
|
1021
1035
|
version = version.to_i
|
1022
|
-
sm_table = quote_table_name(ActiveRecord::
|
1036
|
+
sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
|
1023
1037
|
|
1024
|
-
migrated =
|
1038
|
+
migrated = ActiveRecord::SchemaMigration.all_versions.map(&:to_i)
|
1025
1039
|
versions = ActiveRecord::Migrator.migration_files(migrations_paths).map do |file|
|
1026
1040
|
ActiveRecord::Migrator.parse_migration_filename(file).first.to_i
|
1027
1041
|
end
|
@@ -1030,9 +1044,9 @@ module ActiveRecord
|
|
1030
1044
|
execute "INSERT INTO #{sm_table} (version) VALUES (#{quote(version)})"
|
1031
1045
|
end
|
1032
1046
|
|
1033
|
-
inserting = (versions - migrated).select {|v| v < version}
|
1047
|
+
inserting = (versions - migrated).select { |v| v < version }
|
1034
1048
|
if inserting.any?
|
1035
|
-
if (duplicate = inserting.detect {|v| inserting.count(v) > 1})
|
1049
|
+
if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
|
1036
1050
|
raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
|
1037
1051
|
end
|
1038
1052
|
if supports_multi_insert?
|
@@ -1045,7 +1059,7 @@ module ActiveRecord
|
|
1045
1059
|
end
|
1046
1060
|
end
|
1047
1061
|
|
1048
|
-
def type_to_sql(type, limit
|
1062
|
+
def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) # :nodoc:
|
1049
1063
|
type = type.to_sym if type
|
1050
1064
|
if native = native_database_types[type]
|
1051
1065
|
column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
|
@@ -1063,7 +1077,7 @@ module ActiveRecord
|
|
1063
1077
|
raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale is specified"
|
1064
1078
|
end
|
1065
1079
|
|
1066
|
-
elsif [:datetime, :time].include?(type) && precision ||= native[:precision]
|
1080
|
+
elsif [:datetime, :timestamp, :time, :interval].include?(type) && precision ||= native[:precision]
|
1067
1081
|
if (0..6) === precision
|
1068
1082
|
column_type_sql << "(#{precision})"
|
1069
1083
|
else
|
@@ -1080,7 +1094,7 @@ module ActiveRecord
|
|
1080
1094
|
end
|
1081
1095
|
|
1082
1096
|
# Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT.
|
1083
|
-
# PostgreSQL, MySQL, and Oracle
|
1097
|
+
# PostgreSQL, MySQL, and Oracle override this for custom DISTINCT syntax - they
|
1084
1098
|
# require the order columns appear in the SELECT.
|
1085
1099
|
#
|
1086
1100
|
# columns_for_distinct("posts.id", ["posts.created_at desc"])
|
@@ -1123,7 +1137,6 @@ module ActiveRecord
|
|
1123
1137
|
index_type ||= options[:unique] ? "UNIQUE" : ""
|
1124
1138
|
index_name = options[:name].to_s if options.key?(:name)
|
1125
1139
|
index_name ||= index_name(table_name, column_names)
|
1126
|
-
max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
|
1127
1140
|
|
1128
1141
|
if options.key?(:algorithm)
|
1129
1142
|
algorithm = index_algorithms.fetch(options[:algorithm]) {
|
@@ -1137,10 +1150,9 @@ module ActiveRecord
|
|
1137
1150
|
index_options = options[:where] ? " WHERE #{options[:where]}" : ""
|
1138
1151
|
end
|
1139
1152
|
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
if data_source_exists?(table_name) && index_name_exists?(table_name, index_name, false)
|
1153
|
+
validate_index_length!(table_name, index_name, options.fetch(:internal, false))
|
1154
|
+
|
1155
|
+
if data_source_exists?(table_name) && index_name_exists?(table_name, index_name)
|
1144
1156
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
|
1145
1157
|
end
|
1146
1158
|
index_columns = quoted_columns_for_index(column_names, options).join(", ")
|
@@ -1162,7 +1174,10 @@ module ActiveRecord
|
|
1162
1174
|
raise NotImplementedError, "#{self.class} does not support changing column comments"
|
1163
1175
|
end
|
1164
1176
|
|
1165
|
-
|
1177
|
+
private
|
1178
|
+
def column_options_keys
|
1179
|
+
[:limit, :precision, :scale, :default, :null, :collation, :comment]
|
1180
|
+
end
|
1166
1181
|
|
1167
1182
|
def add_index_sort_order(quoted_columns, **options)
|
1168
1183
|
if order = options[:order]
|
@@ -1197,10 +1212,6 @@ module ActiveRecord
|
|
1197
1212
|
def index_name_for_remove(table_name, options = {})
|
1198
1213
|
return options[:name] if can_remove_index_by_name?(options)
|
1199
1214
|
|
1200
|
-
# if the adapter doesn't support the indexes call the best we can do
|
1201
|
-
# is return the default index name for the options provided
|
1202
|
-
return index_name(table_name, options) unless respond_to?(:indexes)
|
1203
|
-
|
1204
1215
|
checks = []
|
1205
1216
|
|
1206
1217
|
if options.is_a?(Hash)
|
@@ -1250,56 +1261,65 @@ module ActiveRecord
|
|
1250
1261
|
end
|
1251
1262
|
end
|
1252
1263
|
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
end
|
1264
|
+
def create_table_definition(*args)
|
1265
|
+
TableDefinition.new(*args)
|
1266
|
+
end
|
1257
1267
|
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1268
|
+
def create_alter_table(name)
|
1269
|
+
AlterTable.new create_table_definition(name)
|
1270
|
+
end
|
1261
1271
|
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1272
|
+
def index_column_names(column_names)
|
1273
|
+
if column_names.is_a?(String) && /\W/.match?(column_names)
|
1274
|
+
column_names
|
1275
|
+
else
|
1276
|
+
Array(column_names)
|
1277
|
+
end
|
1267
1278
|
end
|
1268
|
-
end
|
1269
1279
|
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1280
|
+
def index_name_options(column_names)
|
1281
|
+
if column_names.is_a?(String) && /\W/.match?(column_names)
|
1282
|
+
column_names = column_names.scan(/\w+/).join("_")
|
1283
|
+
end
|
1284
|
+
|
1285
|
+
{ column: column_names }
|
1273
1286
|
end
|
1274
1287
|
|
1275
|
-
|
1276
|
-
|
1288
|
+
def foreign_key_name(table_name, options)
|
1289
|
+
identifier = "#{table_name}_#{options.fetch(:column)}_fk"
|
1290
|
+
hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
|
1291
|
+
options.fetch(:name) do
|
1292
|
+
"fk_rails_#{hashed_identifier}"
|
1293
|
+
end
|
1294
|
+
end
|
1277
1295
|
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1296
|
+
def validate_index_length!(table_name, new_name, internal = false)
|
1297
|
+
max_index_length = internal ? index_name_length : allowed_index_name_length
|
1298
|
+
|
1299
|
+
if new_name.length > max_index_length
|
1300
|
+
raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters"
|
1301
|
+
end
|
1283
1302
|
end
|
1284
|
-
end
|
1285
1303
|
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1304
|
+
def extract_new_default_value(default_or_changes)
|
1305
|
+
if default_or_changes.is_a?(Hash) && default_or_changes.has_key?(:from) && default_or_changes.has_key?(:to)
|
1306
|
+
default_or_changes[:to]
|
1307
|
+
else
|
1308
|
+
default_or_changes
|
1309
|
+
end
|
1289
1310
|
end
|
1290
|
-
end
|
1291
1311
|
|
1292
|
-
|
1293
|
-
|
1294
|
-
default_or_changes[:to]
|
1295
|
-
else
|
1296
|
-
default_or_changes
|
1312
|
+
def can_remove_index_by_name?(options)
|
1313
|
+
options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
|
1297
1314
|
end
|
1298
|
-
end
|
1299
1315
|
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1316
|
+
def data_source_sql(name = nil, type: nil)
|
1317
|
+
raise NotImplementedError
|
1318
|
+
end
|
1319
|
+
|
1320
|
+
def quoted_scope(name = nil, type: nil)
|
1321
|
+
raise NotImplementedError
|
1322
|
+
end
|
1303
1323
|
end
|
1304
1324
|
end
|
1305
1325
|
end
|
@@ -41,7 +41,6 @@ module ActiveRecord
|
|
41
41
|
end
|
42
42
|
|
43
43
|
class Transaction #:nodoc:
|
44
|
-
|
45
44
|
attr_reader :connection, :state, :records, :savepoint_name
|
46
45
|
attr_writer :joinable
|
47
46
|
|
@@ -101,7 +100,6 @@ module ActiveRecord
|
|
101
100
|
end
|
102
101
|
|
103
102
|
class SavepointTransaction < Transaction
|
104
|
-
|
105
103
|
def initialize(connection, savepoint_name, options, *args)
|
106
104
|
super(connection, options, *args)
|
107
105
|
if options[:isolation]
|
@@ -124,7 +122,6 @@ module ActiveRecord
|
|
124
122
|
end
|
125
123
|
|
126
124
|
class RealTransaction < Transaction
|
127
|
-
|
128
125
|
def initialize(connection, options, *args)
|
129
126
|
super
|
130
127
|
if options[:isolation]
|
@@ -152,57 +149,67 @@ module ActiveRecord
|
|
152
149
|
end
|
153
150
|
|
154
151
|
def begin_transaction(options = {})
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
152
|
+
@connection.lock.synchronize do
|
153
|
+
run_commit_callbacks = !current_transaction.joinable?
|
154
|
+
transaction =
|
155
|
+
if @stack.empty?
|
156
|
+
RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
|
157
|
+
else
|
158
|
+
SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options,
|
159
|
+
run_commit_callbacks: run_commit_callbacks)
|
160
|
+
end
|
163
161
|
|
164
|
-
|
165
|
-
|
162
|
+
@stack.push(transaction)
|
163
|
+
transaction
|
164
|
+
end
|
166
165
|
end
|
167
166
|
|
168
167
|
def commit_transaction
|
169
|
-
|
168
|
+
@connection.lock.synchronize do
|
169
|
+
transaction = @stack.last
|
170
170
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
171
|
+
begin
|
172
|
+
transaction.before_commit_records
|
173
|
+
ensure
|
174
|
+
@stack.pop
|
175
|
+
end
|
176
176
|
|
177
|
-
|
178
|
-
|
177
|
+
transaction.commit
|
178
|
+
transaction.commit_records
|
179
|
+
end
|
179
180
|
end
|
180
181
|
|
181
182
|
def rollback_transaction(transaction = nil)
|
182
|
-
|
183
|
-
|
184
|
-
|
183
|
+
@connection.lock.synchronize do
|
184
|
+
transaction ||= @stack.pop
|
185
|
+
transaction.rollback
|
186
|
+
transaction.rollback_records
|
187
|
+
end
|
185
188
|
end
|
186
189
|
|
187
190
|
def within_new_transaction(options = {})
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
191
|
+
@connection.lock.synchronize do
|
192
|
+
begin
|
193
|
+
transaction = begin_transaction options
|
194
|
+
yield
|
195
|
+
rescue Exception => error
|
196
|
+
if transaction
|
197
|
+
rollback_transaction
|
198
|
+
after_failure_actions(transaction, error)
|
199
|
+
end
|
200
|
+
raise
|
201
|
+
ensure
|
202
|
+
unless error
|
203
|
+
if Thread.current.status == "aborting"
|
204
|
+
rollback_transaction if transaction
|
205
|
+
else
|
206
|
+
begin
|
207
|
+
commit_transaction
|
208
|
+
rescue Exception
|
209
|
+
rollback_transaction(transaction) unless transaction.state.completed?
|
210
|
+
raise
|
211
|
+
end
|
212
|
+
end
|
206
213
|
end
|
207
214
|
end
|
208
215
|
end
|
@@ -226,7 +233,6 @@ module ActiveRecord
|
|
226
233
|
return unless error.is_a?(ActiveRecord::PreparedStatementCacheExpired)
|
227
234
|
@connection.clear_cache!
|
228
235
|
end
|
229
|
-
|
230
236
|
end
|
231
237
|
end
|
232
238
|
end
|