PostgreSQL’s COPY FROM STDIN and Ruby

I stumbled over this and could not find a good example for it so here is my solution.

If you want to import a lot of data into a PostgreSQL database then most propably you want to use one COPY … FROM statement instead of a INSERT statement for every record to create. Let’s assume we want to import some data from Ruby using the raw postgres library.

You can COPY from file which is propably the simplest way of using it:

COPY articles
FROM FILE 'articles.csv'
WITH DELIMITER AS ',';

However, this only works if you are a PostgreSQL super user and the file is on the server. So: How do we solve it? We use COPY FROM STDIN! But, wait… we are inside our Ruby script - what is STDIN? Reading PostgreSQL’s documentation yields that it is the connection from our client library to the server. How can we write to this stream?

The solution is to send the COPY … FROM STDIN statement to the server. The server will then wait for the data. We send the CVS data with PGconn#putline and close the data submission with PGConn#endcopy. That’s it.

Let’s look at an example:

require 'postgres'
conn = PGconn.open('dbname' => 'my_database')
res  = conn.exec(%Q{COPY articles FROM STDIN WITH DELIMITER AS ','})

file_contents = File.open('articles.csv', 'r') { |f| f.read }
file_contents.each_line { |line| conn.putline(line) }
conn.endcopy
conn.close

2 Responses to “PostgreSQL’s COPY FROM STDIN and Ruby”

  1. Jason’s postings and stuff » Rails Migrations and PostgreSQL COPY Says:

    [...] I admit it. I am bad. I run raw SQL in my migrations. The dataset I am working with requires it of me. It must be punished. To aid in its punishment, I found a post explaining how to get at PostgreSQL’s COPY from within the Postgres Ruby driver. [...]

  2. inside wow wizard Says:

    Please tell me it worked right? I dont want to sumit it again if i do not have to! Either the blog glitced out or i am an idiot, the second option doesnt surprise me lol. thanks for a great blog!

Leave a Reply