diff options
author | Bogdan <bogdanvlviv@gmail.com> | 2019-03-05 00:57:38 +0200 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2019-03-04 14:57:38 -0800 |
commit | a8c0ebccbdbf4e2ccbacbf94cba6cf24699af190 (patch) | |
tree | 0767c1a1138c4a670384fc8bc6a1e3ac7b23e879 /activerecord/lib | |
parent | 076e8eddf4766a27a62fd0ae087c6c08501ddc42 (diff) | |
download | rails-a8c0ebccbdbf4e2ccbacbf94cba6cf24699af190.tar.gz rails-a8c0ebccbdbf4e2ccbacbf94cba6cf24699af190.tar.bz2 rails-a8c0ebccbdbf4e2ccbacbf94cba6cf24699af190.zip |
Allow `truncate` for SQLite3 adapter and add `rails db:seed:replant` (#34779)
* Add `ActiveRecord::Base.connection.truncate` for SQLite3 adapter.
SQLite doesn't support `TRUNCATE TABLE`, but SQLite3 adapter can support
`ActiveRecord::Base.connection.truncate` by using `DELETE FROM`.
`DELETE` without `WHERE` uses "The Truncate Optimization",
see https://www.sqlite.org/lang_delete.html.
* Add `rails db:seed:replant` that truncates database tables and loads the seeds
Closes #34765
Diffstat (limited to 'activerecord/lib')
6 files changed, 64 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 9f28fdf749..63e07932d9 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -154,6 +154,10 @@ module ActiveRecord @statements.clear end + def truncate(table_name, name = nil) + execute "DELETE FROM #{quote_table_name(table_name)}", name + end + def supports_index_sort_order? true end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 8de06e8466..f021a8f6c4 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -66,6 +66,11 @@ db_namespace = namespace :db do end end + # desc "Truncates tables of each database for current environment" + task truncate_all: [:load_config, :check_protected_environments] do + ActiveRecord::Tasks::DatabaseTasks.truncate_all + end + # desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:purge:all to purge all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases." task purge: [:load_config, :check_protected_environments] do ActiveRecord::Tasks::DatabaseTasks.purge_current @@ -223,6 +228,11 @@ db_namespace = namespace :db do ActiveRecord::Tasks::DatabaseTasks.load_seed end + namespace :seed do + desc "Truncates tables of each database for current environment and loads the seeds" + task replant: [:load_config, :truncate_all, :seed] + end + namespace :fixtures do desc "Loads fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures." task load: :load_config do diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 27e401a756..ef02ca8190 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -182,6 +182,24 @@ module ActiveRecord } end + def truncate_tables(configuration) + ActiveRecord::Base.connected_to(database: { truncation: configuration }) do + table_names = ActiveRecord::Base.connection.tables + internal_table_names = [ + ActiveRecord::Base.schema_migrations_table_name, + ActiveRecord::Base.internal_metadata_table_name + ] + + class_for_adapter(configuration["adapter"]).new(configuration).truncate_tables(*table_names.without(*internal_table_names)) + end + end + + def truncate_all(environment = env) + ActiveRecord::Base.configurations.configs_for(env_name: environment).each do |db_config| + truncate_tables db_config.config + end + end + def migrate check_target_version diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb index 1c1b29b5e1..f2b4ead98d 100644 --- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb @@ -31,6 +31,16 @@ module ActiveRecord connection.recreate_database configuration["database"], creation_options end + def truncate_tables(*table_names) + return if table_names.empty? + + ActiveRecord::Base.connection.disable_referential_integrity do + table_names.each do |table_name| + ActiveRecord::Base.connection.truncate(table_name) + end + end + end + def charset connection.charset end diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index 8acb11f75f..dc368eb97d 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -48,6 +48,18 @@ module ActiveRecord create true end + def truncate_tables(*table_names) + return if table_names.empty? + + ActiveRecord::Base.connection.disable_referential_integrity do + quoted_table_names = table_names.map do |table_name| + ActiveRecord::Base.connection.quote_table_name(table_name) + end + + ActiveRecord::Base.connection.execute "TRUNCATE TABLE #{quoted_table_names.join(", ")}" + end + end + def structure_dump(filename, extra_flags) set_psql_env diff --git a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb index a82cea80ca..cedbae6b7f 100644 --- a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb @@ -33,6 +33,16 @@ module ActiveRecord create end + def truncate_tables(*table_names) + return if table_names.empty? + + ActiveRecord::Base.connection.disable_referential_integrity do + table_names.each do |table_name| + ActiveRecord::Base.connection.truncate(table_name) + end + end + end + def charset connection.encoding end |