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
Related
The new multi-database feature is great, however it is unclear to me how you can still execute raw mysql calling ActiveRecord::Base.connection.execute and have it select a specific database in the database.yml file.
this
ActiveRecord::Base.connected_to(role: :reading) do
end
Doesnt accept a database
ActiveRecord::Base.connection.execute always seems to USE the first database in the config file.
thanks
Tried: ActiveRecord::Base.connected_to do ...
doesn't expect a database
I am trying to seed sql file that looks like that:
COPY courses (id, name, "courseID", school_id, created_at, updated_at) FROM stdin;
1 Fundamentals of Programming CSCI150 1 2016-04-27 14:04:07.460825 2016-04-27 14:04:07.460825
I try this code:
connection = ActiveRecord::Base.connection
# migrate all courses
sql = File.read('db/nurate.sql')
statements = sql.split(/;$/)
#statements.pop
ActiveRecord::Base.transaction do
statements.each do |statement|
connection.execute(statement)
end
end
Previously I used this code for INSERT etc statements. But here I have error as follows:
PG::UnableToSend: another command is already in progress
So Believe this has something to do with the fact that my sql dump file contains "COPY" statements. What can I do with this? I don't want to change the whole file to use INSERT statements. Or is it the only solution?
I've got same issue and it costed me couple of days.
Firstly I guess that you've used the sql from dump export feature of postgres. So because of that when ever you call
connection.execute(statement)
It will cause error because it's never been a legit call for query in postgresql with provide input data. I've done some check over internet. It seem this thread provide some helpful information.
Okei so in order to keep using buck copy combine with the sql file export by pg_dump, I have come up with quite dirty code (IMO)
unless Rails.env.production?
connection = ActiveRecord::Base.connection
connection.tables.each do |table|
connection.execute("TRUNCATE #{table}") unless table == "schema_migrations"
end
# Create a sql file with purely COPY data and ignoring schema_migrations data
cmd = %x[awk -v RS='' '/COPY/{if (!match($0,/schema/)) print $0}' #{Rails.root}/db/dump.sql> #{Rails.root}/db/temp.sql]
puts cmd
# Restoring sql data to postgres data. Putting password to env variable is never been smart
cmd = %x[PGPASSWORD=#{ActiveRecord::Base.connection_config[:password]} psql --host #{ActiveRecord::Base.connection_config[:host]} -U #{ActiveRecord::Base.connection_config[:username]} --dbname #{ActiveRecord::Base.connection_config[:database]} -1 -f #{Rails.root}/db/temp.sql]
puts cmd
# remove the deed
cmd = %x[rm #{Rails.root}/db/temp.sql]
puts cmd
end
This question already has answers here:
Rails + Postgres drop error: database is being accessed by other users
(20 answers)
Closed 9 years ago.
Is there a way to force a database reset even if Postgres has other users using it. I almost always get this error when I try a $ rake db:reset:
Couldn't drop example_database_name :
#<ActiveRecord::StatementInvalid: PG::Error: ERROR: database "example_database_name" is being accessed by other users DETAIL:
There are 2 other session(s) using the database.
Put this in a file lib/database.rake if you find yourself using db:reset a lot in development.
require 'active_record/connection_adapters/postgresql_adapter'
module ActiveRecord
module ConnectionAdapters
class PostgreSQLAdapter < AbstractAdapter
def drop_database(name)
raise "Nah, I won't drop the production database" if Rails.env.production?
execute <<-SQL
UPDATE pg_catalog.pg_database
SET datallowconn=false WHERE datname='#{name}'
SQL
execute <<-SQL
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = '#{name}';
SQL
execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
end
end
end
end
Obviously only designed for use on non-production databases. It will cause all existing db connections to be severed, so the next page load might be an error if unicorn/passenger/pow is pooling db connections. If this happens, a simple page refresh will cause the server to open a new connection and all will be well.
if the connected sessions are from your rails process - you definitely want to stop rails, strange things could occur if you drop and rebuild the db from underneath the running process
anyhow the following can be run from the command line to drop postgres connections
psql -c "SELECT pid, pg_terminate_backend(pid) as terminated FROM pg_stat_activity WHERE pid <> pg_backend_pid();" -d 'example_database_name'
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
I have a migration that runs an SQL script to create a new Postgres schema. When creating a new database in Postgres by default it creates a schema called 'public', which is the main schema we use. The migration to create the new database schema seems to be working fine, however the problem occurs after the migration has run, when rails tries to update the 'schema_info' table that it relies on it says that it does not exist, as if it is looking for it in the new database schema and not the default 'public' schema where the table actually is.
Does anybody know how I can tell rails to look at the 'public' schema for this table?
Example of SQL being executed: ~
CREATE SCHEMA new_schema;
COMMENT ON SCHEMA new_schema IS 'this is the new Postgres database schema to sit along side the "public" schema';
-- various tables, triggers and functions created in new_schema
Error being thrown: ~
RuntimeError: ERROR C42P01 Mrelation "schema_info" does not exist
L221 RRangeVarGetRelid: UPDATE schema_info SET version = ??
Thanks for your help
Chris Knight
Well that depends what your migration looks like, what your database.yml looks like and what exactly you are trying to attempt. Anyway more information is needed change the names if you have to and post an example database.yml and the migration. does the migration change the search_path for the adapter for example ?
But know that in general rails and postgresql schemas don't work well together (yet?).
There are a few places which have problems. Try and build and app that uses only one pg database with 2 non-default schemas one for dev and one for test and tell me about it. (from thefollowing I can already tell you that you will get burned)
Maybe it was fixed since the last time I played with it but when I see http://rails.lighthouseapp.com/projects/8994/tickets/390-postgres-adapter-quotes-table-name-breaks-when-non-default-schema-is-used or this http://rails.lighthouseapp.com/projects/8994/tickets/918-postgresql-tables-not-generating-correct-schema-list or this in postgresql_adapter.rb
# Drops a PostgreSQL database
#
# Example:
# drop_database 'matt_development'
def drop_database(name) #:nodoc:
execute "DROP DATABASE IF EXISTS #{name}"
end
(yes this is wrong if you use the same database with different schemas for both dev and test, this would drop both databases each time you run the unit tests !)
I actually started writing patches. the first one was for the indexes methods in the adapter which didn't care about the search_path ending up with duplicated indexes in some conditions, then I started getting hurt by the rest and ended up abandonning the idea of using schemas: I wanted to get my app done and I didn't have the extra time needed to fix the problems I had using schemas.
I'm not sure I understand what you're asking exactly, but, rake will be expecting to update the version of the Rails schema into the schema_info table. Check your database.yml config file, this is where rake will be looking to find the table to update.
Is it a possibility that you are migrating to a new Postgres schema and rake is still pointing to the old one? I'm not sure then that a standard Rails migration is what you need. It might be best to create your own rake task instead.
Edit: If you're referencing two different databases or Postgres schemas, Rails doesn't support this in standard migrations. Rails assumes one database, so migrations from one database to another is usually not possible. When you run "rake db:migrate" it actually looks at the RAILS_ENV environment variable to find the correct entry in database.yml. If rake starts the migration looking at the "development" environment and database config from database.yml, it will expect to update to this environment at the end of the migration.
So, you'll probably need to do this from outside the Rails stack as you can't reference two databases at the same time within Rails. There are attempts at plugins to allow this, but they're majorly hacky and don't work properly.
You can use pg_power. It provides additional DSL for migration to create PostgreSQL schemas and not only.