truncate and restart identity of a set of tables - ruby-on-rails

My application uses Postgresql.
I would need to remove all rows from a set of tables (table1 to table4) and restart the id with one command from a rb file.
In the Postgresql documentation I found that TRUNCATE with RESTART IDENTITY would do the job as follows:
TRUNCATE table1, table2, table3, table4 RESTART IDENTITY;
According to How to restart id counting on a table in PostgreSQL after deleting some previous data? at Stackoverflow, I can use the following command:
ActiveRecord::Base.connection.execute("TRUNCATE TABLE your_table_name RESTART IDENTITY")
So putting together the two documentations, would it be correct to use the following command:
ActiveRecord::Base.connection.execute("TRUNCATE table1, table2, table3, table4 RESTART IDENTITY")
considering that in the API dock documentation the connection method is reported as deprecated or moved?.

The recommended way nowadays is to use an ActiveRecord::Base.connection_pool.with_connection block.
ActiveRecord::Base.connection_pool.with_connection do |conn|
conn.execute("TRUNCATE table1, table2, table3, table4 RESTART IDENTITY")
end

Related

Aurora Postgresql's insert statements aren't recognizing existing key IDs

After migrating from RDS Postgresql to RDS Aurora PostgreSQL, I am having an issue to where new inserts are trying to start from key ID 2 instead of the last record.
In my rails app, here's what I'm seeing when I try to create a new record:
ActiveRecord::RecordNotUnique (PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "global_options_pkey"
DETAIL: Key (id)=(3) already exists.
):
app/controllers/schedules_controller.rb:45:in `create'
Not sure why this would be the case. To set up Aurora PSQL in Rails, I followed this tutorial: https://guides.rubyonrails.org/active_record_multiple_databases.html. It seems like everything is working fine (auto switching between reader/writer instances, etc.).
With the migration, I specifically used the AWS Schema Conversion Tool (SCT), followed by a migration with the Database Migration Service.
Is this error caused by something that was done incorrectly in the migration process or do I need to some post-migration processes to have this fixed?
Definitely a case of when you migrated old data, but not with INSERT and your sequences are still on the initial values.
Use sequence manipulation functions to check what is the current value with lastval(), and set it to max(id) with setval()
You can try
ActiveRecord::Base.connection.tables.each do |table_name|
ActiveRecord::Base.connection.reset_pk_sequence!(table_name)
end

rails postgres some of the sequence not start from 1

I am using ruby on rails with postgresql database. A weird thing happened that some of the tables_id_seq are not starting from 1, but 980190963. But some of the seq are correctly starting from 1.
The problem is when I tried to insert data into those table which seq not start from 1, unique primary key violation raised occasionally.
--EDIT--
I found that when I do
rake db:migrate test
The problem happens.
If I do
rake db:migrate RAILS_ENV=test
The problem has gone.
If you don't need to keep the data in those tables, you can run the following which will reset the table (THIS WILL REMOVE ANY DATA THERE) and restart the tables id to start at 1. THIS IS ONLY VIABLE IF YOU DON"T NEED THE DATA IN THAT TABLE!
ActiveRecord::Base.connection.execute("TRUNCATE TABLE table_name_here RESTART IDENTITY")
As far as why your tables are starting at that id value I would start by checking your migrations. Maybe somewhere in the code there is an "Alter Sequence" sql statement but again not sure.

truncate all data in model and restart the id

I have several records in my Category model. All of them are test data. Now I want to clear the data.
if I issue Category.destroy_all or Category.delete_all all the records are deleted. However, any newly created record does not start with id 1. If I had 10 records previously, the new category after I destroy the previous records start at 11.
How do I force restart id from 1?
ActiveRecord::Base.connection.execute("TRUNCATE TABLE #{table_name}")
You can run choose to run it:
in rails console
in seed.rb file if you don't have console access. (Make a method in category model that you will run only once. (rake db:seed))
app/model/category.rb :
def truncate_me!
ActiveRecord::Base.connection.execute("TRUNCATE TABLE #{table_name}")
end
db/seed.rb
Category.truncate_me!
3. in a migration
If you have access to database you can also run an actual TRUNCATE query.
You could redo the migration with the following command:
rake db:migrate:redo VERSION=your_category_migration_version
This will drop the category table and recreate it. If you have other migrations that change category table then you would need to run those too.
After executing the above rake task, you can run your seed task.

How to delete everything from all tables without dropping the database [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Truncating all tables in a postgres database
How can I delete all data from all tables without dropping the database?
You can use raw connection object to execute SQL statements:
connection = ActiveRecord::Base.connection
connection.tables.each{|t| connection.execute "TRUNCATE #{t}"}
Use the DatabaseCleaner gem.
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean
If you absolutely must have this within a rake task, just wrap it up in one yourself.
For ad-hoc use
Run this statement in the database (Careful! Nukes all your data!):
DO
$func$
BEGIN
EXECUTE (
SELECT 'TRUNCATE TABLE '
|| string_agg(quote_ident(t.tablename), ', ')
|| ' CASCADE'
FROM pg_tables t
WHERE t.schemaname = 'public' -- assuming default schema
);
END
$func$;
The DO command was introduced with PostgreSQL 9.0. You would create a plpgsql function and execute it for older versions.
Compare to the closely related question: Truncating all tables in a Postgres database
For repeated use
It might be simpler (and faster!) to create a "template" database (let's name it my_template) with your vanilla structure and all empty tables. Then go through a DROP / CREATE DATABASE cycle:
DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;
This is extremely fast, because PostgreSQL copies the whole structure on the file level. No concurrency issues or other overhead slowing you down.
You can do a backup of the database with pg_dump and restore only the schema of the database with pg_resotre --schema-only , it deletes all data in all tables.
Exemple:
To backup.
pg_dump --format=c --compress=0 -h localhost mydatabasename > mydump.dmp
To restore only schema information without data.
pg_restore -c --schema-only mydump.dmp | psql -h localhost mydatabasename

How can execute multiple statements in one query with Rails?

I am using Ruby on Rails with ActiveRecord and PostgreSQL.
How can i execute multiple sql queries?
I need it for running a custom migration script, eg:
Foo.connection.execute <<-SQL.split(';').map(&:strip).join
delete from metadata where record_type = 'Foo';
TRUNCATE table1 RESTART IDENTITY;
TRUNCATE table2 RESTART IDENTITY;
delete from schema_migrations where version > '20120806120823';
SQL
I am not accepting data from a user, so I'm not worried about sql-injection.
Something like CLIENT_MULTI_STATEMENTS in MySQL maybe ?
From the MySQL/PHP docs:
CLIENT_MULTI_STATEMENTS: Tell the server that the client may send
multiple statements in a single string (separated by “;”). If this
flag is not set, multiple-statement execution is disabled. See the
note following this table for more information about this flag.
It should work out of the box with PostgreSQL, checked with pg gem and rails 3.2:
class Multitest < ActiveRecord::Migration
def up
execute <<-SQL
create table x(id serial primary key);
create table y(id serial primary key, i integer);
SQL
end
def down
end
end
On a side note, manipulating schema_migrations directly looks strange.
For mysql
queries = File.read("/where/is/myqueries.sql")
# or
queries = <<-SQL
TRUNCATE table1 RESTART IDENTITY;
TRUNCATE table2 RESTART IDENTITY;
delete from schema_migrations where version > '20120806120823';
SQL
queries.split(';').map(&:strip).each do |query|
execute(query)
end
You may want see this question too:
Invoking a large set of SQL from a Rails 4 application
Yes, you need CLIENT_MULTI_STATEMENTS:
In database.yml:
development:
adapter: mysql2
database: project_development
flags:
- MULTI_STATEMENTS
Then in your code:
connection.execute(multistatement_query)
# Hack for mysql2 adapter to be able query again after executing multistatement_query
connection.raw_connection.store_result while connection.raw_connection.next_result
See https://stackoverflow.com/a/11246837/338859 for details

Resources