2011-07-21 22 views
5

Tôi có ứng dụng đường ray đã hoạt động thành công trong nhiều tháng. Ở một vài nơi tôi gọi trực tiếp đến cơ sở dữ liệu qua ActiveRecord :: Base.connection.execute (sql_code)Sự cố với lệnh COPY postgresql với Rails trên máy chủ khác nhau

Với nhu cầu quy mô gần đây, tôi vừa thêm máy chủ thứ hai để xử lý dữ liệu. Tôi muốn chạy cùng một ứng dụng nhưng kết nối qua mạng với máy chủ cơ sở dữ liệu khác. Đó là sự khác biệt duy nhất ở đây. Tất cả các lĩnh vực khác của ứng dụng hoạt động - nó có thể kết nối với cơ sở dữ liệu từ xa.

Nơi nó đang bẻ khóa, là nơi tôi có đường ray phát hành lệnh psql COPY để nhập tệp csv.

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

Điều này không thành công và không thể tìm thấy tệp csv. Tôi đã xác minh nó ở đó và có thể đọc được cho cả người dùng đang chạy ứng dụng đường ray và người dùng postgres.

Tôi có thiếu gì đó không?

+3

Tôi cho rằng đó là vì lệnh COPY được ban hành chống lại các máy chủ từ xa những người sau đó vẻ cho tệp csv đã nói trong cấu trúc thư mục của nó và không tìm thấy nó. Rất tiếc. Tôi cần phải tìm một cách khác. –

Trả lời

18

Bạn có thể sử dụng COPY TỪ STDIN để làm được việc này ... như vậy:

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) 

Tôi tin rằng có một số tùy chọn để COPY mà sẽ cho phép bạn chỉ định bạn đang đi qua trong dữ liệu CSV mà sẽ làm cho nó thậm chí còn dễ dàng hơn ...

+1

Sẽ thật thú vị khi đề cập đến cách tiêu thụ và xử lý lỗi tại đây, ví dụ: 'res.result_status' và' res.error_message' –

2

Bạn cũng có thể thử loại này, và thực hiện lệnh với 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

Trong pg-0.17.1 (Rails 4) có một cải thiện PG::Connection::copy_data giao diện để 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 

Bạn thậm chí có thể vượt qua toàn bộ đệm tập tin để put_copy_data nếu bạn không phải lo lắng về việc sử dụng bộ nhớ:

 result = raw.copy_data "COPY my_table FROM STDIN" do 
     raw.put_copy_data File.read(filename) 
     end 
+1

Nếu bạn sử dụng điều này và thấy nó hoạt động trong phát triển nhưng không có trong kiểm tra, điều này có thể là do các thử nghiệm chạy trong một giao dịch và do đó kết nối được kiểm tra do đó bị mù với giao dịch. Vì vậy, hãy thử 'dbconn = ActiveRecord :: Base.connection'instead – novemberkilo

+0

Cảm ơn, tôi đã không hoàn toàn grok connection_pool.checkout và bạn nói đúng - nó đã gây ra rắc rối cho tôi trong các bài kiểm tra giao dịch. – hybernaut

Các vấn đề liên quan