Проблемы с командой COPY postgresql с Rails на другом сервере - PullRequest
8 голосов
/ 21 июля 2011

У меня есть приложение rails, которое успешно работает уже несколько месяцев.В некоторых местах я обращаюсь напрямую к базе данных через ActiveRecord :: Base.connection.execute (sql_code)

В связи с недавней необходимостью масштабирования, я просто добавил второй сервер для обработки данных.Я хочу запустить то же приложение, но подключиться по сети к другому серверу базы данных.Это единственное отличие здесь.Все остальные области приложения работают - оно может подключаться к удаленной базе данных.

Где оно ломается, там, где у меня есть рельсы, введите команду psql COPY для импорта файла csv.

   result = ActiveRecord::Base.connection.execute( @PGSQL_COPY_COMMAND )     # perform the copy command

Это сбой и говорит о том, что CSV-файл не может быть найден.Я убедился, что он есть и доступен для чтения как пользователю, запускающему приложение rails, так и пользователю postgres.

Я что-то упустил?

Ответы [ 3 ]

20 голосов
/ 21 июля 2011

Вы можете использовать COPY FROM STDIN, чтобы обойти это ... вот так:

conn = ActiveRecord::Base.connection_pool.checkout
raw  = conn.raw_connection
raw.exec("COPY tablename (col1, col2, col3) FROM STDIN")
# open up your CSV file looping through line by line and getting the line into a format suitable for pg's COPY...
raw.put_copy_data line
# once all done...
raw.put_copy_end
while res = raw.get_result do; end # very important to do this after a copy
ActiveRecord::Base.connection_pool.checkin(conn)

Я полагаю, что есть некоторые опции для COPY, которые позволят вам указать, что вы передаете данные CSV, что сделает это еще проще ...

12 голосов
/ 18 декабря 2013

В pg-0.17.1 (Rails 4) улучшен интерфейс PG::Connection::copy_data для Postgres COPY.

  def load_file(filename)

    dbconn = ActiveRecord::Base.connection_pool.checkout
    raw  = dbconn.raw_connection
    count = nil

    result = raw.copy_data "COPY my_table FROM STDIN" do

      File.open(filename, 'r').each do |line|
        raw.put_copy_data line
      end

    end

    count = dbconn.select_value("select count(*) from #{ttable}").to_i

    ActiveRecord::Base.connection_pool.checkin(dbconn)

    count
  end

Вы даже можете передать весь файловый буфер в put_copy_data, если вас не беспокоит использование памяти:

      result = raw.copy_data "COPY my_table FROM STDIN" do
        raw.put_copy_data File.read(filename)
      end
2 голосов
/ 12 марта 2013

Вы также можете попробовать это и выполнить команду с помощью psql:

config = YourApp::Application.config.database_configuration[::Rails.env]
dbhost, dbuser, dbname = config['host'], config['username'], config['database']

copy_command = "\\copy theTable (col1, col2, col3) from '/a/path/to/csv' csv header;"
sql_command = "psql -U #{dbuser} -h #{dbhost} #{dbname} -c \"#{copy_command}\""

`#{sql_command}`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...