【问题标题】:Problems with postgresql COPY command with Rails on different server在不同服务器上使用 Rails 的 postgresql COPY 命令问题
【发布时间】:2011-07-21 17:05:53
【问题描述】:

我有一个 Rails 应用程序已经成功运行了几个月。在一些地方,我通过 ActiveRecord::Base.connection.execute( sql_code ) 直接调用数据库

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

问题出在哪里,是我让 rails 发出 psql COPY 命令来导入 csv 文件的地方。

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

这失败并说找不到 csv 文件。我已经验证它在那里并且对于运行 rails 应用程序的用户和 postgres 用户都是可读的。

我错过了什么吗?

【问题讨论】:

  • 我想这是因为向远程服务器发出了 COPY 命令,然后远程服务器在其目录结构中查找所述 csv 文件但没有找到它。真可惜。我需要另辟蹊径。

标签: ruby-on-rails postgresql


【解决方案1】:

您可以使用 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 数据,这将使其更容易...

【讨论】:

  • 在这里提及如何使用和处理错误会很酷,例如使用res.result_statusres.error_message
【解决方案2】:

在 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

【讨论】:

  • 如果您使用它并看到它在开发中工作但在测试中没有,这可能是因为测试在事务中运行,因此签出的连接对事务是盲目的。所以,试试dbconn = ActiveRecord::Base.connectioninstead
  • 谢谢,我没有完全理解connection_pool.checkout,你说得对——它在事务测试中给我带来了麻烦。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-30
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 2011-08-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    相关资源
    最近更新 更多