2011-07-21 22 views
5

Tengo una aplicación de rieles que ha funcionado con éxito durante meses. En algunos lugares llamo directamente a la base de datos a través de ActiveRecord :: Base.connection.execute (código_sql)Problemas con el comando COPY de postgresql con Rails en un servidor diferente

Con una necesidad reciente de escalar, acabo de agregar un segundo servidor para el procesamiento de datos. Quiero ejecutar la misma aplicación pero me conecto a través de la red al otro servidor de base de datos. Esa es la única diferencia aquí. Todas las demás áreas de la aplicación funcionan: se puede conectar a la base de datos remota.

Donde se está rompiendo, es donde tengo los carriles emiten un comando psql COPY para importar un archivo csv.

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

Esto falla y dice que no se puede encontrar el archivo csv. He verificado que está allí y es legible tanto para el usuario que ejecuta la aplicación Rails como para el usuario postgres.

¿Echo de menos algo?

+3

supongo que se debe a que el comando COPY se emitió en contra del servidor remoto que luego mira para dicho archivo csv en su estructura de directorio y no lo encuentra. Gorrón. Necesito encontrar una manera diferente. –

Respuesta

18

puede usar la copia de la entrada estándar de evitar esto ... de este modo:

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) 

Creo que hay algunas opciones de copia que le permitirá especificar que está pasando en los datos CSV que haría que sea aún más fácil ...

+1

Sería genial mencionar cómo consumir y manejar los errores aquí, usando p. Ej. 'res.result_status' y' res.error_message' –

2

también puede probar esto, y ejecutar el comando con 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

en PG-0.17.1 (carriles 4) hay una mejorada interfaz para PG::Connection::copy_data Postgr es COPIA.

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 

Incluso puede pasar todo un búfer de archivo a put_copy_data si no está preocupado por el uso de memoria:

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

Si usa esto y lo ve trabajando en desarrollo pero no en prueba, es probable que esto se deba a que las pruebas se ejecutan en una transacción y, por lo tanto, la conexión desprotegida está cegada a la transacción. Por lo tanto, intente con 'dbconn = ActiveRecord :: Base.connection'instead – novemberkilo

+0

. Gracias, no resolví completamente el connection_pool.checkout y tiene razón, me estaba causando problemas en las pruebas transaccionales. – hybernaut

Cuestiones relacionadas