activerecord 6.0.0 → 6.0.3
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 +185 -1
- data/README.rdoc +1 -1
- data/lib/active_record.rb +1 -0
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +0 -1
- data/lib/active_record/association_relation.rb +10 -8
- data/lib/active_record/associations.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +0 -1
- data/lib/active_record/associations/association.rb +5 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -2
- data/lib/active_record/associations/collection_association.rb +6 -2
- data/lib/active_record/associations/collection_proxy.rb +1 -2
- data/lib/active_record/associations/has_many_association.rb +0 -1
- data/lib/active_record/associations/join_dependency.rb +13 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +1 -1
- data/lib/active_record/associations/preloader.rb +2 -3
- data/lib/active_record/attribute_assignment.rb +0 -1
- data/lib/active_record/attribute_decorators.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +0 -1
- data/lib/active_record/attribute_methods/dirty.rb +2 -2
- data/lib/active_record/attribute_methods/primary_key.rb +0 -2
- data/lib/active_record/attribute_methods/read.rb +0 -1
- data/lib/active_record/attribute_methods/serialization.rb +0 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -2
- data/lib/active_record/attribute_methods/write.rb +0 -1
- data/lib/active_record/attributes.rb +0 -1
- data/lib/active_record/autosave_association.rb +8 -6
- data/lib/active_record/callbacks.rb +1 -2
- data/lib/active_record/coders/yaml_column.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +14 -7
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +21 -15
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +27 -27
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +47 -30
- data/lib/active_record/connection_adapters/abstract/transaction.rb +4 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +23 -8
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +25 -32
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -3
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -12
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -8
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +9 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -29
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +9 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +8 -7
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +12 -7
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_handling.rb +13 -22
- data/lib/active_record/core.rb +8 -6
- data/lib/active_record/counter_cache.rb +4 -1
- data/lib/active_record/database_configurations/url_config.rb +0 -1
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/explain.rb +0 -1
- data/lib/active_record/fixture_set/table_row.rb +0 -1
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +0 -3
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +0 -3
- data/lib/active_record/insert_all.rb +4 -4
- data/lib/active_record/internal_metadata.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +0 -1
- data/lib/active_record/log_subscriber.rb +1 -1
- data/lib/active_record/middleware/database_selector.rb +0 -1
- data/lib/active_record/middleware/database_selector/resolver.rb +9 -14
- data/lib/active_record/migration.rb +4 -4
- data/lib/active_record/migration/command_recorder.rb +6 -18
- data/lib/active_record/migration/compatibility.rb +3 -3
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/model_schema.rb +3 -2
- data/lib/active_record/nested_attributes.rb +0 -2
- data/lib/active_record/no_touching.rb +2 -2
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +4 -5
- data/lib/active_record/querying.rb +1 -1
- data/lib/active_record/railtie.rb +1 -1
- data/lib/active_record/railties/collection_cache_association_loading.rb +1 -1
- data/lib/active_record/railties/databases.rake +3 -0
- data/lib/active_record/reflection.rb +8 -8
- data/lib/active_record/relation.rb +13 -1
- data/lib/active_record/relation/batches.rb +0 -1
- data/lib/active_record/relation/calculations.rb +1 -1
- data/lib/active_record/relation/delegation.rb +7 -6
- data/lib/active_record/relation/finder_methods.rb +10 -2
- data/lib/active_record/relation/from_clause.rb +4 -0
- data/lib/active_record/relation/merger.rb +0 -1
- data/lib/active_record/relation/predicate_builder.rb +1 -5
- data/lib/active_record/relation/query_methods.rb +37 -12
- data/lib/active_record/relation/spawn_methods.rb +0 -1
- data/lib/active_record/relation/where_clause.rb +0 -1
- data/lib/active_record/result.rb +0 -1
- data/lib/active_record/schema_migration.rb +1 -1
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/scoping/default.rb +0 -1
- data/lib/active_record/scoping/named.rb +3 -3
- data/lib/active_record/store.rb +1 -1
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +16 -1
- data/lib/active_record/tasks/mysql_database_tasks.rb +0 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +0 -1
- data/lib/active_record/test_fixtures.rb +2 -1
- data/lib/active_record/timestamp.rb +0 -1
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +9 -9
- data/lib/active_record/type.rb +0 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +0 -1
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/validations.rb +2 -3
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/arel.rb +17 -6
- data/lib/arel/predications.rb +5 -6
- data/lib/arel/visitors/depth_first.rb +0 -1
- data/lib/arel/visitors/dot.rb +0 -1
- data/lib/arel/visitors/mssql.rb +0 -1
- data/lib/arel/visitors/oracle.rb +1 -2
- data/lib/arel/visitors/oracle12.rb +0 -1
- data/lib/arel/visitors/postgresql.rb +0 -1
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +0 -1
- data/lib/arel/visitors/visitor.rb +0 -1
- data/lib/arel/visitors/where_sql.rb +0 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration.rb +0 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +0 -1
- metadata +13 -9
@@ -292,7 +292,7 @@ module ActiveRecord
|
|
292
292
|
#
|
293
293
|
# See also TableDefinition#column for details on how to create columns.
|
294
294
|
def create_table(table_name, **options)
|
295
|
-
td = create_table_definition(table_name, options)
|
295
|
+
td = create_table_definition(table_name, **options)
|
296
296
|
|
297
297
|
if options[:id] != false && !options[:as]
|
298
298
|
pk = options.fetch(:primary_key) do
|
@@ -302,14 +302,14 @@ module ActiveRecord
|
|
302
302
|
if pk.is_a?(Array)
|
303
303
|
td.primary_keys pk
|
304
304
|
else
|
305
|
-
td.primary_key pk, options.fetch(:id, :primary_key), options.except(:comment)
|
305
|
+
td.primary_key pk, options.fetch(:id, :primary_key), **options.except(:comment)
|
306
306
|
end
|
307
307
|
end
|
308
308
|
|
309
309
|
yield td if block_given?
|
310
310
|
|
311
311
|
if options[:force]
|
312
|
-
drop_table(table_name, options
|
312
|
+
drop_table(table_name, **options, if_exists: true)
|
313
313
|
end
|
314
314
|
|
315
315
|
result = execute schema_creation.accept td
|
@@ -378,9 +378,9 @@ module ActiveRecord
|
|
378
378
|
|
379
379
|
t1_ref, t2_ref = [table_1, table_2].map { |t| t.to_s.singularize }
|
380
380
|
|
381
|
-
create_table(join_table_name, options.merge!(id: false)) do |td|
|
382
|
-
td.references t1_ref, column_options
|
383
|
-
td.references t2_ref, column_options
|
381
|
+
create_table(join_table_name, **options.merge!(id: false)) do |td|
|
382
|
+
td.references t1_ref, **column_options
|
383
|
+
td.references t2_ref, **column_options
|
384
384
|
yield td if block_given?
|
385
385
|
end
|
386
386
|
end
|
@@ -391,7 +391,7 @@ module ActiveRecord
|
|
391
391
|
# Although this command ignores the block if one is given, it can be helpful
|
392
392
|
# to provide one in a migration's +change+ method so it can be reverted.
|
393
393
|
# In that case, the block will be used by #create_join_table.
|
394
|
-
def drop_join_table(table_1, table_2, options
|
394
|
+
def drop_join_table(table_1, table_2, **options)
|
395
395
|
join_table_name = find_join_table_name(table_1, table_2, options)
|
396
396
|
drop_table(join_table_name)
|
397
397
|
end
|
@@ -468,7 +468,7 @@ module ActiveRecord
|
|
468
468
|
# end
|
469
469
|
#
|
470
470
|
# See also Table for details on all of the various column transformations.
|
471
|
-
def change_table(table_name, options
|
471
|
+
def change_table(table_name, **options)
|
472
472
|
if supports_bulk_alter? && options[:bulk]
|
473
473
|
recorder = ActiveRecord::Migration::CommandRecorder.new(self)
|
474
474
|
yield update_table_definition(table_name, recorder)
|
@@ -498,7 +498,7 @@ module ActiveRecord
|
|
498
498
|
# Although this command ignores most +options+ and the block if one is given,
|
499
499
|
# it can be helpful to provide these in a migration's +change+ method so it can be reverted.
|
500
500
|
# In that case, +options+ and the block will be used by #create_table.
|
501
|
-
def drop_table(table_name, options
|
501
|
+
def drop_table(table_name, **options)
|
502
502
|
execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
|
503
503
|
end
|
504
504
|
|
@@ -587,7 +587,7 @@ module ActiveRecord
|
|
587
587
|
# # ALTER TABLE "shapes" ADD "triangle" polygon
|
588
588
|
def add_column(table_name, column_name, type, **options)
|
589
589
|
at = create_alter_table table_name
|
590
|
-
at.add_column(column_name, type, options)
|
590
|
+
at.add_column(column_name, type, **options)
|
591
591
|
execute schema_creation.accept at
|
592
592
|
end
|
593
593
|
|
@@ -610,8 +610,8 @@ module ActiveRecord
|
|
610
610
|
# to provide these in a migration's +change+ method so it can be reverted.
|
611
611
|
# In that case, +type+ and +options+ will be used by #add_column.
|
612
612
|
# Indexes on the column are automatically removed.
|
613
|
-
def remove_column(table_name, column_name, type = nil, options
|
614
|
-
execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, options)}"
|
613
|
+
def remove_column(table_name, column_name, type = nil, **options)
|
614
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, **options)}"
|
615
615
|
end
|
616
616
|
|
617
617
|
# Changes the column's definition according to the new options.
|
@@ -783,7 +783,7 @@ module ActiveRecord
|
|
783
783
|
#
|
784
784
|
# For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
|
785
785
|
def add_index(table_name, column_name, options = {})
|
786
|
-
index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, options)
|
786
|
+
index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, **options)
|
787
787
|
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})#{index_options}"
|
788
788
|
end
|
789
789
|
|
@@ -902,7 +902,7 @@ module ActiveRecord
|
|
902
902
|
# add_reference(:products, :supplier, foreign_key: {to_table: :firms})
|
903
903
|
#
|
904
904
|
def add_reference(table_name, ref_name, **options)
|
905
|
-
ReferenceDefinition.new(ref_name, options).add_to(update_table_definition(table_name, self))
|
905
|
+
ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
|
906
906
|
end
|
907
907
|
alias :add_belongs_to :add_reference
|
908
908
|
|
@@ -930,7 +930,7 @@ module ActiveRecord
|
|
930
930
|
foreign_key_options = { to_table: reference_name }
|
931
931
|
end
|
932
932
|
foreign_key_options[:column] ||= "#{ref_name}_id"
|
933
|
-
remove_foreign_key(table_name, foreign_key_options)
|
933
|
+
remove_foreign_key(table_name, **foreign_key_options)
|
934
934
|
end
|
935
935
|
|
936
936
|
remove_column(table_name, "#{ref_name}_id")
|
@@ -988,7 +988,7 @@ module ActiveRecord
|
|
988
988
|
# Action that happens <tt>ON UPDATE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
|
989
989
|
# [<tt>:validate</tt>]
|
990
990
|
# (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+.
|
991
|
-
def add_foreign_key(from_table, to_table, options
|
991
|
+
def add_foreign_key(from_table, to_table, **options)
|
992
992
|
return unless supports_foreign_keys?
|
993
993
|
|
994
994
|
options = foreign_key_options(from_table, to_table, options)
|
@@ -1145,22 +1145,22 @@ module ActiveRecord
|
|
1145
1145
|
#
|
1146
1146
|
# add_timestamps(:suppliers, null: true)
|
1147
1147
|
#
|
1148
|
-
def add_timestamps(table_name, options
|
1148
|
+
def add_timestamps(table_name, **options)
|
1149
1149
|
options[:null] = false if options[:null].nil?
|
1150
1150
|
|
1151
1151
|
if !options.key?(:precision) && supports_datetime_with_precision?
|
1152
1152
|
options[:precision] = 6
|
1153
1153
|
end
|
1154
1154
|
|
1155
|
-
add_column table_name, :created_at, :datetime, options
|
1156
|
-
add_column table_name, :updated_at, :datetime, options
|
1155
|
+
add_column table_name, :created_at, :datetime, **options
|
1156
|
+
add_column table_name, :updated_at, :datetime, **options
|
1157
1157
|
end
|
1158
1158
|
|
1159
1159
|
# Removes the timestamp columns (+created_at+ and +updated_at+) from the table definition.
|
1160
1160
|
#
|
1161
1161
|
# remove_timestamps(:suppliers)
|
1162
1162
|
#
|
1163
|
-
def remove_timestamps(table_name, options
|
1163
|
+
def remove_timestamps(table_name, **options)
|
1164
1164
|
remove_column table_name, :updated_at
|
1165
1165
|
remove_column table_name, :created_at
|
1166
1166
|
end
|
@@ -1196,7 +1196,7 @@ module ActiveRecord
|
|
1196
1196
|
if data_source_exists?(table_name) && index_name_exists?(table_name, index_name)
|
1197
1197
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
|
1198
1198
|
end
|
1199
|
-
index_columns = quoted_columns_for_index(column_names, options).join(", ")
|
1199
|
+
index_columns = quoted_columns_for_index(column_names, **options).join(", ")
|
1200
1200
|
|
1201
1201
|
[index_name, index_type, index_columns, index_options, algorithm, using, comment]
|
1202
1202
|
end
|
@@ -1253,7 +1253,7 @@ module ActiveRecord
|
|
1253
1253
|
# the PostgreSQL adapter for supporting operator classes.
|
1254
1254
|
def add_options_for_index_columns(quoted_columns, **options)
|
1255
1255
|
if supports_index_sort_order?
|
1256
|
-
quoted_columns = add_index_sort_order(quoted_columns, options)
|
1256
|
+
quoted_columns = add_index_sort_order(quoted_columns, **options)
|
1257
1257
|
end
|
1258
1258
|
|
1259
1259
|
quoted_columns
|
@@ -1263,7 +1263,7 @@ module ActiveRecord
|
|
1263
1263
|
return [column_names] if column_names.is_a?(String)
|
1264
1264
|
|
1265
1265
|
quoted_columns = Hash[column_names.map { |name| [name.to_sym, quote_column_name(name).dup] }]
|
1266
|
-
add_options_for_index_columns(quoted_columns, options).values
|
1266
|
+
add_options_for_index_columns(quoted_columns, **options).values
|
1267
1267
|
end
|
1268
1268
|
|
1269
1269
|
def index_name_for_remove(table_name, options = {})
|
@@ -1322,8 +1322,8 @@ module ActiveRecord
|
|
1322
1322
|
SchemaCreation.new(self)
|
1323
1323
|
end
|
1324
1324
|
|
1325
|
-
def create_table_definition(*args)
|
1326
|
-
TableDefinition.new(self, *args)
|
1325
|
+
def create_table_definition(*args, **options)
|
1326
|
+
TableDefinition.new(self, *args, **options)
|
1327
1327
|
end
|
1328
1328
|
|
1329
1329
|
def create_alter_table(name)
|
@@ -1374,7 +1374,7 @@ module ActiveRecord
|
|
1374
1374
|
|
1375
1375
|
def foreign_key_for(from_table, **options)
|
1376
1376
|
return unless supports_foreign_keys?
|
1377
|
-
foreign_keys(from_table).detect { |fk| fk.defined_for?(options) }
|
1377
|
+
foreign_keys(from_table).detect { |fk| fk.defined_for?(**options) }
|
1378
1378
|
end
|
1379
1379
|
|
1380
1380
|
def foreign_key_for!(from_table, to_table: nil, **options)
|
@@ -1436,20 +1436,37 @@ module ActiveRecord
|
|
1436
1436
|
non_combinable_operations.each(&:call)
|
1437
1437
|
end
|
1438
1438
|
|
1439
|
-
def add_column_for_alter(table_name, column_name, type, options
|
1439
|
+
def add_column_for_alter(table_name, column_name, type, **options)
|
1440
1440
|
td = create_table_definition(table_name)
|
1441
|
-
cd = td.new_column_definition(column_name, type, options)
|
1441
|
+
cd = td.new_column_definition(column_name, type, **options)
|
1442
1442
|
schema_creation.accept(AddColumnDefinition.new(cd))
|
1443
1443
|
end
|
1444
1444
|
|
1445
|
-
def remove_column_for_alter(table_name, column_name, type = nil, options
|
1445
|
+
def remove_column_for_alter(table_name, column_name, type = nil, **options)
|
1446
1446
|
"DROP COLUMN #{quote_column_name(column_name)}"
|
1447
1447
|
end
|
1448
1448
|
|
1449
|
-
def remove_columns_for_alter(table_name, *column_names)
|
1449
|
+
def remove_columns_for_alter(table_name, *column_names, **options)
|
1450
1450
|
column_names.map { |column_name| remove_column_for_alter(table_name, column_name) }
|
1451
1451
|
end
|
1452
1452
|
|
1453
|
+
def add_timestamps_for_alter(table_name, **options)
|
1454
|
+
options[:null] = false if options[:null].nil?
|
1455
|
+
|
1456
|
+
if !options.key?(:precision) && supports_datetime_with_precision?
|
1457
|
+
options[:precision] = 6
|
1458
|
+
end
|
1459
|
+
|
1460
|
+
[
|
1461
|
+
add_column_for_alter(table_name, :created_at, :datetime, **options),
|
1462
|
+
add_column_for_alter(table_name, :updated_at, :datetime, **options)
|
1463
|
+
]
|
1464
|
+
end
|
1465
|
+
|
1466
|
+
def remove_timestamps_for_alter(table_name, **options)
|
1467
|
+
remove_columns_for_alter(table_name, :updated_at, :created_at)
|
1468
|
+
end
|
1469
|
+
|
1453
1470
|
def insert_versions_sql(versions)
|
1454
1471
|
sm_table = quote_table_name(schema_migration.table_name)
|
1455
1472
|
|
@@ -98,7 +98,7 @@ module ActiveRecord
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def rollback_records
|
101
|
-
ite = records.uniq(&:
|
101
|
+
ite = records.uniq(&:__id__)
|
102
102
|
already_run_callbacks = {}
|
103
103
|
while record = ite.shift
|
104
104
|
trigger_callbacks = record.trigger_transactional_callbacks?
|
@@ -117,7 +117,7 @@ module ActiveRecord
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def commit_records
|
120
|
-
ite = records.uniq(&:
|
120
|
+
ite = records.uniq(&:__id__)
|
121
121
|
already_run_callbacks = {}
|
122
122
|
while record = ite.shift
|
123
123
|
if @run_commit_callbacks
|
@@ -141,8 +141,8 @@ module ActiveRecord
|
|
141
141
|
end
|
142
142
|
|
143
143
|
class SavepointTransaction < Transaction
|
144
|
-
def initialize(connection, savepoint_name, parent_transaction, *args)
|
145
|
-
super(connection, *args)
|
144
|
+
def initialize(connection, savepoint_name, parent_transaction, *args, **options)
|
145
|
+
super(connection, *args, **options)
|
146
146
|
|
147
147
|
parent_transaction.state.add_child(@state)
|
148
148
|
|
@@ -309,7 +309,6 @@ module ActiveRecord
|
|
309
309
|
end
|
310
310
|
|
311
311
|
private
|
312
|
-
|
313
312
|
NULL_TRANSACTION = NullTransaction.new
|
314
313
|
|
315
314
|
# Deallocate invalidated prepared statements outside of the transaction
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "set"
|
3
4
|
require "active_record/connection_adapters/determine_if_preparable_visitor"
|
4
5
|
require "active_record/connection_adapters/schema_cache"
|
5
6
|
require "active_record/connection_adapters/sql_type_metadata"
|
@@ -11,7 +12,6 @@ require "arel/collectors/bind"
|
|
11
12
|
require "arel/collectors/composite"
|
12
13
|
require "arel/collectors/sql_string"
|
13
14
|
require "arel/collectors/substitute_binds"
|
14
|
-
require "concurrent/atomic/thread_local_var"
|
15
15
|
|
16
16
|
module ActiveRecord
|
17
17
|
module ConnectionAdapters # :nodoc:
|
@@ -77,6 +77,7 @@ module ActiveRecord
|
|
77
77
|
include Savepoints
|
78
78
|
|
79
79
|
SIMPLE_INT = /\A\d+\z/
|
80
|
+
COMMENT_REGEX = %r{/\*(?:[^\*]|\*[^/])*\*/}m
|
80
81
|
|
81
82
|
attr_accessor :pool
|
82
83
|
attr_reader :visitor, :owner, :logger, :lock
|
@@ -103,8 +104,8 @@ module ActiveRecord
|
|
103
104
|
end
|
104
105
|
|
105
106
|
def self.build_read_query_regexp(*parts) # :nodoc:
|
106
|
-
parts = parts.map { |part|
|
107
|
-
Regexp.union(*parts)
|
107
|
+
parts = parts.map { |part| /#{part}/i }
|
108
|
+
/\A(?:[\(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
|
108
109
|
end
|
109
110
|
|
110
111
|
def self.quoted_column_names # :nodoc:
|
@@ -130,10 +131,10 @@ module ActiveRecord
|
|
130
131
|
@lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
|
131
132
|
|
132
133
|
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
133
|
-
@
|
134
|
+
@prepared_statements = true
|
134
135
|
@visitor.extend(DetermineIfPreparableVisitor)
|
135
136
|
else
|
136
|
-
@
|
137
|
+
@prepared_statements = false
|
137
138
|
end
|
138
139
|
|
139
140
|
@advisory_locks_enabled = self.class.type_cast_config_to_boolean(
|
@@ -177,7 +178,11 @@ module ActiveRecord
|
|
177
178
|
end
|
178
179
|
|
179
180
|
def prepared_statements
|
180
|
-
@
|
181
|
+
@prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
|
182
|
+
end
|
183
|
+
|
184
|
+
def prepared_statements_disabled_cache # :nodoc:
|
185
|
+
Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new
|
181
186
|
end
|
182
187
|
|
183
188
|
class Version
|
@@ -264,7 +269,10 @@ module ActiveRecord
|
|
264
269
|
end
|
265
270
|
|
266
271
|
def unprepared_statement
|
267
|
-
|
272
|
+
cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
|
273
|
+
yield
|
274
|
+
ensure
|
275
|
+
cache&.delete(object_id)
|
268
276
|
end
|
269
277
|
|
270
278
|
# Returns the human-readable name of the adapter. Use mixed case - one
|
@@ -305,6 +313,10 @@ module ActiveRecord
|
|
305
313
|
false
|
306
314
|
end
|
307
315
|
|
316
|
+
def supports_partitioned_indexes?
|
317
|
+
false
|
318
|
+
end
|
319
|
+
|
308
320
|
# Does this adapter support index sort order?
|
309
321
|
def supports_index_sort_order?
|
310
322
|
false
|
@@ -409,6 +421,10 @@ module ActiveRecord
|
|
409
421
|
false
|
410
422
|
end
|
411
423
|
|
424
|
+
def supports_common_table_expressions?
|
425
|
+
false
|
426
|
+
end
|
427
|
+
|
412
428
|
def supports_lazy_transactions?
|
413
429
|
false
|
414
430
|
end
|
@@ -609,7 +625,6 @@ module ActiveRecord
|
|
609
625
|
end
|
610
626
|
|
611
627
|
private
|
612
|
-
|
613
628
|
def type_map
|
614
629
|
@type_map ||= Type::TypeMap.new.tap do |mapping|
|
615
630
|
initialize_type_map(mapping)
|
@@ -45,7 +45,6 @@ module ActiveRecord
|
|
45
45
|
|
46
46
|
class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
|
47
47
|
private
|
48
|
-
|
49
48
|
def dealloc(stmt)
|
50
49
|
stmt.close
|
51
50
|
end
|
@@ -110,6 +109,14 @@ module ActiveRecord
|
|
110
109
|
!mariadb? && database_version >= "5.7.7"
|
111
110
|
end
|
112
111
|
|
112
|
+
def supports_common_table_expressions?
|
113
|
+
if mariadb?
|
114
|
+
database_version >= "10.2.1"
|
115
|
+
else
|
116
|
+
database_version >= "8.0.1"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
113
120
|
def supports_advisory_locks?
|
114
121
|
true
|
115
122
|
end
|
@@ -359,7 +366,7 @@ module ActiveRecord
|
|
359
366
|
end
|
360
367
|
|
361
368
|
def add_index(table_name, column_name, options = {}) #:nodoc:
|
362
|
-
index_name, index_type, index_columns, _, index_algorithm, index_using, comment = add_index_options(table_name, column_name, options)
|
369
|
+
index_name, index_type, index_columns, _, index_algorithm, index_using, comment = add_index_options(table_name, column_name, **options)
|
363
370
|
sql = +"CREATE #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} ON #{quote_table_name(table_name)} (#{index_columns}) #{index_algorithm}"
|
364
371
|
execute add_sql_comment!(sql, comment)
|
365
372
|
end
|
@@ -411,12 +418,13 @@ module ActiveRecord
|
|
411
418
|
create_table_info = create_table_info(table_name)
|
412
419
|
|
413
420
|
# strip create_definitions and partition_options
|
414
|
-
|
421
|
+
# Be aware that `create_table_info` might not include any table options due to `NO_TABLE_OPTIONS` sql mode.
|
422
|
+
raw_table_options = create_table_info.sub(/\A.*\n\) ?/m, "").sub(/\n\/\*!.*\*\/\n\z/m, "").strip
|
415
423
|
|
416
424
|
# strip AUTO_INCREMENT
|
417
425
|
raw_table_options.sub!(/(ENGINE=\w+)(?: AUTO_INCREMENT=\d+)/, '\1')
|
418
426
|
|
419
|
-
table_options[:options] = raw_table_options
|
427
|
+
table_options[:options] = raw_table_options unless raw_table_options.blank?
|
420
428
|
|
421
429
|
# strip COMMENT
|
422
430
|
if raw_table_options.sub!(/ COMMENT='.+'/, "")
|
@@ -440,11 +448,11 @@ module ActiveRecord
|
|
440
448
|
|
441
449
|
query_values(<<~SQL, "SCHEMA")
|
442
450
|
SELECT column_name
|
443
|
-
FROM information_schema.
|
444
|
-
WHERE
|
451
|
+
FROM information_schema.statistics
|
452
|
+
WHERE index_name = 'PRIMARY'
|
445
453
|
AND table_schema = #{scope[:schema]}
|
446
454
|
AND table_name = #{scope[:name]}
|
447
|
-
ORDER BY
|
455
|
+
ORDER BY seq_in_index
|
448
456
|
SQL
|
449
457
|
end
|
450
458
|
|
@@ -485,7 +493,7 @@ module ActiveRecord
|
|
485
493
|
def columns_for_distinct(columns, orders) # :nodoc:
|
486
494
|
order_columns = orders.reject(&:blank?).map { |s|
|
487
495
|
# Convert Arel node to string
|
488
|
-
s = s
|
496
|
+
s = visitor.compile(s) unless s.is_a?(String)
|
489
497
|
# Remove any ASC/DESC modifiers
|
490
498
|
s.gsub(/\s+(?:ASC|DESC)\b/i, "")
|
491
499
|
}.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
|
@@ -522,7 +530,6 @@ module ActiveRecord
|
|
522
530
|
end
|
523
531
|
|
524
532
|
private
|
525
|
-
|
526
533
|
def initialize_type_map(m = type_map)
|
527
534
|
super
|
528
535
|
|
@@ -562,12 +569,12 @@ module ActiveRecord
|
|
562
569
|
end
|
563
570
|
end
|
564
571
|
|
565
|
-
def register_integer_type(mapping, key, options)
|
572
|
+
def register_integer_type(mapping, key, **options)
|
566
573
|
mapping.register_type(key) do |sql_type|
|
567
574
|
if /\bunsigned\b/.match?(sql_type)
|
568
|
-
Type::UnsignedInteger.new(options)
|
575
|
+
Type::UnsignedInteger.new(**options)
|
569
576
|
else
|
570
|
-
Type::Integer.new(options)
|
577
|
+
Type::Integer.new(**options)
|
571
578
|
end
|
572
579
|
end
|
573
580
|
end
|
@@ -581,6 +588,7 @@ module ActiveRecord
|
|
581
588
|
end
|
582
589
|
|
583
590
|
# See https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html
|
591
|
+
ER_FILSORT_ABORT = 1028
|
584
592
|
ER_DUP_ENTRY = 1062
|
585
593
|
ER_NOT_NULL_VIOLATION = 1048
|
586
594
|
ER_NO_REFERENCED_ROW = 1216
|
@@ -622,7 +630,7 @@ module ActiveRecord
|
|
622
630
|
Deadlocked.new(message, sql: sql, binds: binds)
|
623
631
|
when ER_LOCK_WAIT_TIMEOUT
|
624
632
|
LockWaitTimeout.new(message, sql: sql, binds: binds)
|
625
|
-
when ER_QUERY_TIMEOUT
|
633
|
+
when ER_QUERY_TIMEOUT, ER_FILSORT_ABORT
|
626
634
|
StatementTimeout.new(message, sql: sql, binds: binds)
|
627
635
|
when ER_QUERY_INTERRUPTED
|
628
636
|
QueryCanceled.new(message, sql: sql, binds: binds)
|
@@ -648,7 +656,7 @@ module ActiveRecord
|
|
648
656
|
end
|
649
657
|
|
650
658
|
td = create_table_definition(table_name)
|
651
|
-
cd = td.new_column_definition(column.name, type, options)
|
659
|
+
cd = td.new_column_definition(column.name, type, **options)
|
652
660
|
schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
|
653
661
|
end
|
654
662
|
|
@@ -662,12 +670,12 @@ module ActiveRecord
|
|
662
670
|
|
663
671
|
current_type = exec_query("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE #{quote(column_name)}", "SCHEMA").first["Type"]
|
664
672
|
td = create_table_definition(table_name)
|
665
|
-
cd = td.new_column_definition(new_column_name, current_type, options)
|
673
|
+
cd = td.new_column_definition(new_column_name, current_type, **options)
|
666
674
|
schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
|
667
675
|
end
|
668
676
|
|
669
677
|
def add_index_for_alter(table_name, column_name, options = {})
|
670
|
-
index_name, index_type, index_columns, _, index_algorithm, index_using = add_index_options(table_name, column_name, options)
|
678
|
+
index_name, index_type, index_columns, _, index_algorithm, index_using = add_index_options(table_name, column_name, **options)
|
671
679
|
index_algorithm[0, 0] = ", " if index_algorithm.present?
|
672
680
|
"ADD #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_algorithm}"
|
673
681
|
end
|
@@ -677,20 +685,6 @@ module ActiveRecord
|
|
677
685
|
"DROP INDEX #{quote_column_name(index_name)}"
|
678
686
|
end
|
679
687
|
|
680
|
-
def add_timestamps_for_alter(table_name, options = {})
|
681
|
-
options[:null] = false if options[:null].nil?
|
682
|
-
|
683
|
-
if !options.key?(:precision) && supports_datetime_with_precision?
|
684
|
-
options[:precision] = 6
|
685
|
-
end
|
686
|
-
|
687
|
-
[add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
|
688
|
-
end
|
689
|
-
|
690
|
-
def remove_timestamps_for_alter(table_name, options = {})
|
691
|
-
[remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
|
692
|
-
end
|
693
|
-
|
694
688
|
def supports_rename_index?
|
695
689
|
mariadb? ? false : database_version >= "5.7.6"
|
696
690
|
end
|
@@ -787,7 +781,7 @@ module ActiveRecord
|
|
787
781
|
options[:primary_key_column] = column_for(match[:target_table], match[:primary_key])
|
788
782
|
end
|
789
783
|
|
790
|
-
MismatchedForeignKey.new(options)
|
784
|
+
MismatchedForeignKey.new(**options)
|
791
785
|
end
|
792
786
|
|
793
787
|
def version_string(full_version_string)
|
@@ -804,7 +798,6 @@ module ActiveRecord
|
|
804
798
|
end
|
805
799
|
|
806
800
|
private
|
807
|
-
|
808
801
|
def cast_value(value)
|
809
802
|
case value
|
810
803
|
when true then "1"
|