Execute sql script inside seed.rb in rails3 - ruby-on-rails

I want to execute this sql script inside my seed.rb
LOAD DATA LOCAL INFILE '/home/list-38.csv'
INTO TABLE list
FIELDS TERMINATED BY ':'
LINES TERMINATED BY '\n'
(email,name,password);
I checked this link but unable to figure out the solution.So that once we run rake db:seed
How to seed mysql database by running sql scripts in Ruby Rails platform? it dumps my data into the table.
any queries ..do reply
Thanx

Try this in db/seeds.rb to execute raw SQL with rake db:seed
connection = ActiveRecord::Base.connection()
connection.execute("*_YOUR_SQL_HERE_*")

For multiple sql statements, I ended up iterating over each statement separately:
# db/seeds.rb
connection = ActiveRecord::Base.connection()
sql = <<-EOL
INSERT INTO users values ('Admin');
INSERT INTO categories values ('Supervisors');
EOL
sql.split(';').each do |s|
connection.execute(s.strip) unless s.strip.empty?
end

A variation on Fredrik Boström's answer that can load from a file:
# db/seeds.rb
def execute_sql_file(path, connection = ActiveRecord::Base.connection)
require 'active_support/core_ext/object/blank.rb'
IO.read(path).split(';').reject(&:blank?).each do |statement|
connection.execute(statement)
end
end
execute_sql_file('my.sql')

Super late to this answer but hopefully it helps someone in my position. Instead of iterating over each sql statement you can use .execute_batch using a direct connection to your database with the database version you are using. Below is an example with SQLite3.
#db/seeds.rb
DB = {:conn => SQLite3::Database.new("./db/development.sqlite")}
sql = <<-EOL
INSERT INTO users values ('Admin');
INSERT INTO categories values ('Supervisors');
EOL
DB[:conn].execute_batch(sql)

Related

Rails 7 - selecting database with multi-database when calling ActiveRecord::Base.connection.execute

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

Rails seed sql file that contains "COPY" statments

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

Can I write PostgreSQL functions on Ruby on Rails?

We are starting a project based on Ruby on Rails. We used to work with Perl and PostgreSQL functions, and with Rails and Active Record I've not seen how we are supposed to create functions in PostgreSQL and keep the record with Active Record and models.
I know we can create it manually in PostgreSQL, but the "magic" with Active Record is that the database can be recreated with all the models.
Is there any way to create the PostgreSQL function using Rails and keep it in the models?
This part of your question:
I know we can create it manually in PostgreSQL, but the "magic" with Active Record is that the database can be recreated with all the models.
tells me that you're really looking for a way to integrate PostgreSQL functions with the normal Rails migration process and Rake tasks such as db:schema:load.
Adding and removing functions in migrations is easy:
def up
connection.execute(%q(
create or replace function ...
))
end
def down
connection.execute(%q(
drop function ...
))
end
You need to use separate up and down methods instead of a single change method because ActiveRecord will have no idea how to apply let alone reverse a function creation. And you use connection.execute to feed the raw function definition to PostgreSQL. You can also do this with a reversible inside change:
def change
reversible do |dir|
dir.up do
connection.execute(%q(
create or replace function ...
))
end
dir.down do
connection.execute(%q(
drop function ...
))
end
end
end
but I find that noisier than up and down.
However, schema.rb and the usual Rake tasks that work with schema.rb (such as db:schema:load and db:schema:dump) won't know what to do with PostgreSQL functions and other things that ActiveRecord doesn't understand. There is a way around this though, you can choose to use a structure.sql file instead of schema.rb by setting:
config.active_record.schema_format = :sql
in your config/application.rb file. After that, db:migrate will write a db/structure.sql file (which is just a raw SQL dump of your PostgreSQL database without your data) instead of db/schema.rb. You'll also use different Rake tasks for working with structure.sql:
db:structure:dump instead of db:schema:dump
db:structure:load instead of db:schema:load
Everything else should work the same.
This approach also lets you use other things in your database that ActiveRecord won't understand: CHECK constraints, triggers, non-simple-minded column defaults, ...
If your only requirement is creating them somewhere in your Rails app, this is possible through ActiveRecord::Base.connection.execute, which you can use to execute raw SQL queries.
stmt = 'CREATE FUNCTION...'
ActiveRecord::Base.connection.execute stmt
You would then call the function using ActiveRecord::Base.connection.execute as well (I'd imagine you'd have methods in your model to handle this).

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