Method: PostgresCopy::ActsAsCopyTarget::CopyMethods#copy_from
- Defined in:
- lib/postgres-copy/acts_as_copy_target.rb
#copy_from(path_or_io, options = {}) ⇒ Object
Copy data from a CSV that can be passed as a string (the file path) or as an IO object.
-
You can change the default delimiter passing delimiter: ” in the options hash
-
You can map fields from the file to different fields in the table using a map in the options hash
-
For further details on usage take a look at the README.md
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/postgres-copy/acts_as_copy_target.rb', line 82 def copy_from path_or_io, = {} = { delimiter: ",", format: :csv, header: true, quote: '"' }.merge() [:delimiter] = "\t" if [:format] == :tsv = if [:format] == :binary "BINARY" else quote = [:quote] == "'" ? "''" : [:quote] null = .key?(:null) ? "NULL '#{[:null]}'" : nil force_null = .key?(:force_null) ? "FORCE_NULL(#{[:force_null].join(',')})" : nil delimiter = [:format] == :tsv ? "E'\t'" : "'#{[:delimiter]}'" "WITH (" + ["DELIMITER #{delimiter}", "QUOTE '#{quote}'", null, force_null, "FORMAT CSV"].compact.join(', ') + ")" end io = path_or_io.instance_of?(String) ? File.open(path_or_io, get_file_mode('r', [:encoding])) : path_or_io if [:format] == :binary columns_list = [:columns] || [] elsif [:header] line = io.gets columns_list = [:columns] || line.strip.split([:delimiter]) else columns_list = [:columns] end table = if [:table] connection.quote_table_name([:table]) else quoted_table_name end columns_list = columns_list.map{|c| [:map][c.to_s] || c.to_s } if [:map] columns_string = columns_list.size > 0 ? "(\"#{columns_list.join('","')}\")" : "" connection.raw_connection.copy_data %{COPY #{table} #{columns_string} FROM STDIN #{}} do if [:format] == :binary bytes = 0 begin while line = io.readpartial(10240) connection.raw_connection.put_copy_data line bytes += line.bytesize end rescue EOFError end else line_buffer = '' while line = io.gets do next if line.strip.size == 0 line_buffer += line # If line is incomplete, get the next line until it terminates if line_buffer =~ /\n$/ || line_buffer =~ /\Z/ if block_given? begin row = CSV.parse_line(line_buffer.strip, col_sep: [:delimiter]) yield(row) next if row.all?(&:nil?) line_buffer = CSV.generate_line(row, col_sep: [:delimiter]) rescue CSV::MalformedCSVError next end end connection.raw_connection.put_copy_data(line_buffer) # Clear the buffer line_buffer = '' end end end end end |