2011-07-21 19 views
5

我有一个Rails应用程序已成功运行数月。在一些地方,我通过ActiveRecord :: Base.connection.execute直接调用数据库(sql_code)与不同的服务器上的Rails postgresql COPY命令的问题

随着最近需要扩展,我刚添加了第二台数据处理服务器。我想运行相同的应用程序,但通过网络连接到其他数据库服务器。这是唯一的区别。该应用程序的所有其他领域的工作 - 它可以连接到远程数据库。

它在哪里打破,我有rails的地方发出一个psql COPY命令来导入一个csv文件。

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

此失败并表示无法找到csv文件。我已验证它在那里,并且对运行rails应用程序和postgres用户的用户都可读。

我错过了什么吗?

+3

我想这是因为COPY命令获取对远程服务器发出谁再容貌对于目录结构中的所述csv文件并且没有找到它。游民。我需要找到一种不同的方式。 –

回答

18

您可以使用COPY从标准输入来解决这个问题......像这样:

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) 

我相信有一些选项来复制将让您指定要传递的CSV数据这将使它更容易...

+1

这里很酷,提及如何使用和处理错误。 'res.result_status'和'res.error_message' –

2

你也可以试试这个,并用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}` 
7

在PG-0.17.1(轨道4)有一个改进的PG::Connection::copy_data接口Postgr es 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 
+1

如果你使用它并且看到它在开发中工作,但是没有在测试中,这很可能是因为测试在事务中运行,因此检出的连接对事务是无效的。所以,试试'dbconn = ActiveRecord :: Base.connection'代替 – novemberkilo

+0

谢谢,我没有完全理解connection_pool.checkout,你说得对 - 它在事务测试中给我造成了麻烦。 – hybernaut