postgres-copy 1.5.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +6 -1
- data/Gemfile.lock +17 -62
- data/README.md +7 -0
- data/lib/postgres-copy/acts_as_copy_target.rb +15 -7
- data/postgres-copy.gemspec +1 -2
- data/spec/copy_from_spec.rb +12 -0
- data/spec/fixtures/comma_with_bom.csv +2 -0
- data/spec/fixtures/comma_with_header_to_map.csv +2 -0
- metadata +5 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfe11c5653d850edd47a3df54bcbb83600f820b35a297f05d363b6e89b8b27ff
|
4
|
+
data.tar.gz: 25a187d205ca18ad00e9a35de9a3fabc400137a56af61fce58eac5f7713491af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf7bdfb2fc14b24ede0973c7e573ed30507c77c205cfe87aa13f9302ad31d988360bcebec83b5ee1c83d266c14d8b42728fb17d5a07c222babc3aab5438562ce
|
7
|
+
data.tar.gz: b0f085dbbd1fbd684a00d97eda965f7074d52b8e8f0fe07657f33a5a5fcbd9ab4041a71956e640c5b40140c125675f20479044e1aea5b7bea1d1aba9d51e4227
|
data/.github/workflows/ruby.yml
CHANGED
@@ -33,6 +33,10 @@ jobs:
|
|
33
33
|
--health-retries 5
|
34
34
|
|
35
35
|
runs-on: ubuntu-latest
|
36
|
+
name: test (ruby v${{ matrix.ruby }})
|
37
|
+
strategy:
|
38
|
+
matrix:
|
39
|
+
ruby: ["2.7", "3.0", "3.1"]
|
36
40
|
|
37
41
|
steps:
|
38
42
|
- uses: actions/checkout@v2
|
@@ -41,7 +45,8 @@ jobs:
|
|
41
45
|
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
42
46
|
uses: ruby/setup-ruby@v1
|
43
47
|
with:
|
44
|
-
ruby-version:
|
48
|
+
ruby-version: ${{ matrix.ruby }}
|
49
|
+
bundler-cache: true
|
45
50
|
- name: Install dependencies
|
46
51
|
run: bundle install
|
47
52
|
- name: Run tests
|
data/Gemfile.lock
CHANGED
@@ -1,73 +1,31 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
postgres-copy (1.
|
4
|
+
postgres-copy (1.6.1)
|
5
5
|
activerecord (>= 5.1)
|
6
6
|
pg (>= 0.17)
|
7
|
-
responders
|
8
7
|
|
9
8
|
GEM
|
10
9
|
remote: https://rubygems.org/
|
11
10
|
specs:
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
19
|
-
actionview (6.0.3.2)
|
20
|
-
activesupport (= 6.0.3.2)
|
21
|
-
builder (~> 3.1)
|
22
|
-
erubi (~> 1.4)
|
23
|
-
rails-dom-testing (~> 2.0)
|
24
|
-
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
25
|
-
activemodel (6.0.3.2)
|
26
|
-
activesupport (= 6.0.3.2)
|
27
|
-
activerecord (6.0.3.2)
|
28
|
-
activemodel (= 6.0.3.2)
|
29
|
-
activesupport (= 6.0.3.2)
|
30
|
-
activesupport (6.0.3.2)
|
11
|
+
activemodel (7.0.4)
|
12
|
+
activesupport (= 7.0.4)
|
13
|
+
activerecord (7.0.4)
|
14
|
+
activemodel (= 7.0.4)
|
15
|
+
activesupport (= 7.0.4)
|
16
|
+
activesupport (7.0.4)
|
31
17
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
32
|
-
i18n (>=
|
33
|
-
minitest (
|
34
|
-
tzinfo (~>
|
35
|
-
|
36
|
-
builder (3.2.4)
|
37
|
-
concurrent-ruby (1.1.6)
|
38
|
-
crass (1.0.6)
|
18
|
+
i18n (>= 1.6, < 2)
|
19
|
+
minitest (>= 5.1)
|
20
|
+
tzinfo (~> 2.0)
|
21
|
+
concurrent-ruby (1.1.10)
|
39
22
|
diff-lcs (1.4.4)
|
40
|
-
|
41
|
-
i18n (1.8.3)
|
23
|
+
i18n (1.12.0)
|
42
24
|
concurrent-ruby (~> 1.0)
|
43
|
-
|
44
|
-
|
45
|
-
nokogiri (>= 1.5.9)
|
46
|
-
method_source (1.0.0)
|
47
|
-
mini_portile2 (2.4.0)
|
48
|
-
minitest (5.14.1)
|
49
|
-
nokogiri (1.10.10)
|
50
|
-
mini_portile2 (~> 2.4.0)
|
51
|
-
pg (1.2.3)
|
52
|
-
rack (2.2.3)
|
53
|
-
rack-test (1.1.0)
|
54
|
-
rack (>= 1.0, < 3)
|
55
|
-
rails-dom-testing (2.0.3)
|
56
|
-
activesupport (>= 4.2.0)
|
57
|
-
nokogiri (>= 1.6)
|
58
|
-
rails-html-sanitizer (1.3.0)
|
59
|
-
loofah (~> 2.3)
|
60
|
-
railties (6.0.3.2)
|
61
|
-
actionpack (= 6.0.3.2)
|
62
|
-
activesupport (= 6.0.3.2)
|
63
|
-
method_source
|
64
|
-
rake (>= 0.8.7)
|
65
|
-
thor (>= 0.20.3, < 2.0)
|
25
|
+
minitest (5.16.3)
|
26
|
+
pg (1.4.3)
|
66
27
|
rake (11.2.2)
|
67
28
|
rdoc (6.2.1)
|
68
|
-
responders (3.0.1)
|
69
|
-
actionpack (>= 5.0)
|
70
|
-
railties (>= 5.0)
|
71
29
|
rspec (2.99.0)
|
72
30
|
rspec-core (~> 2.99.0)
|
73
31
|
rspec-expectations (~> 2.99.0)
|
@@ -76,11 +34,8 @@ GEM
|
|
76
34
|
rspec-expectations (2.99.2)
|
77
35
|
diff-lcs (>= 1.1.3, < 2.0)
|
78
36
|
rspec-mocks (2.99.4)
|
79
|
-
|
80
|
-
|
81
|
-
tzinfo (1.2.7)
|
82
|
-
thread_safe (~> 0.1)
|
83
|
-
zeitwerk (2.4.0)
|
37
|
+
tzinfo (2.0.5)
|
38
|
+
concurrent-ruby (~> 1.0)
|
84
39
|
|
85
40
|
PLATFORMS
|
86
41
|
ruby
|
@@ -93,4 +48,4 @@ DEPENDENCIES
|
|
93
48
|
rspec (~> 2.12)
|
94
49
|
|
95
50
|
BUNDLED WITH
|
96
|
-
2.
|
51
|
+
2.2.22
|
data/README.md
CHANGED
@@ -200,6 +200,13 @@ Which will generate the following SQL command:
|
|
200
200
|
COPY users (id, name) FROM '/tmp/users.dat' WITH BINARY
|
201
201
|
```
|
202
202
|
|
203
|
+
To specify the encoding with which to read the file, set the :encoding option.
|
204
|
+
This is useful for removing byte order marks when matching column headers.
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
User.copy_from "/tmp/users_with_byte_order_mark.csv", :encoding => 'bom|utf-8'
|
208
|
+
```
|
209
|
+
|
203
210
|
|
204
211
|
### Using the CSV Responder
|
205
212
|
If you want to make the result of a COPY command available to download this gem provides a CSV responder that, in conjunction with [inherited_resources](https://github.com/josevalim/inherited_resources), is a very powerfull tool. BTW, do not try to use the responder without inherited_resources.
|
@@ -1,5 +1,13 @@
|
|
1
1
|
require 'csv'
|
2
2
|
|
3
|
+
def get_file_mode mode, encoding = nil
|
4
|
+
if encoding
|
5
|
+
"#{mode}:#{encoding}"
|
6
|
+
else
|
7
|
+
mode
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
3
11
|
module PostgresCopy
|
4
12
|
module ActsAsCopyTarget
|
5
13
|
extend ActiveSupport::Concern
|
@@ -10,7 +18,7 @@ module PostgresCopy
|
|
10
18
|
module CopyMethods
|
11
19
|
# Copy data to a file passed as a string (the file path) or to lines that are passed to a block
|
12
20
|
def copy_to path = nil, options = {}
|
13
|
-
options = {:
|
21
|
+
options = { delimiter: ",", format: :csv, header: true }.merge(options)
|
14
22
|
options_string = if options[:format] == :binary
|
15
23
|
"BINARY"
|
16
24
|
else
|
@@ -72,7 +80,7 @@ module PostgresCopy
|
|
72
80
|
# * You can map fields from the file to different fields in the table using a map in the options hash
|
73
81
|
# * For further details on usage take a look at the README.md
|
74
82
|
def copy_from path_or_io, options = {}
|
75
|
-
options = {:
|
83
|
+
options = { delimiter: ",", format: :csv, header: true, quote: '"' }.merge(options)
|
76
84
|
options[:delimiter] = "\t" if options[:format] == :tsv
|
77
85
|
options_string = if options[:format] == :binary
|
78
86
|
"BINARY"
|
@@ -83,7 +91,7 @@ module PostgresCopy
|
|
83
91
|
delimiter = options[:format] == :tsv ? "E'\t'" : "'#{options[:delimiter]}'"
|
84
92
|
"WITH (" + ["DELIMITER #{delimiter}", "QUOTE '#{quote}'", null, force_null, "FORMAT CSV"].compact.join(', ') + ")"
|
85
93
|
end
|
86
|
-
io = path_or_io.instance_of?(String) ? File.open(path_or_io, 'r') : path_or_io
|
94
|
+
io = path_or_io.instance_of?(String) ? File.open(path_or_io, get_file_mode('r', options[:encoding])) : path_or_io
|
87
95
|
|
88
96
|
if options[:format] == :binary
|
89
97
|
columns_list = options[:columns] || []
|
@@ -100,7 +108,7 @@ module PostgresCopy
|
|
100
108
|
quoted_table_name
|
101
109
|
end
|
102
110
|
|
103
|
-
columns_list = columns_list.map{|c| options[:map][c.to_s] } if options[:map]
|
111
|
+
columns_list = columns_list.map{|c| options[:map][c.to_s] || c.to_s } if options[:map]
|
104
112
|
columns_string = columns_list.size > 0 ? "(\"#{columns_list.join('","')}\")" : ""
|
105
113
|
connection.raw_connection.copy_data %{COPY #{table} #{columns_string} FROM STDIN #{options_string}} do
|
106
114
|
if options[:format] == :binary
|
@@ -124,10 +132,10 @@ module PostgresCopy
|
|
124
132
|
if line_buffer =~ /\n$/ || line_buffer =~ /\Z/
|
125
133
|
if block_given?
|
126
134
|
begin
|
127
|
-
row = CSV.parse_line(line_buffer.strip,
|
135
|
+
row = CSV.parse_line(line_buffer.strip, col_sep: options[:delimiter])
|
128
136
|
yield(row)
|
129
|
-
next if row.all?
|
130
|
-
line_buffer = CSV.generate_line(row,
|
137
|
+
next if row.all?(&:nil?)
|
138
|
+
line_buffer = CSV.generate_line(row, col_sep: options[:delimiter])
|
131
139
|
rescue CSV::MalformedCSVError
|
132
140
|
next
|
133
141
|
end
|
data/postgres-copy.gemspec
CHANGED
@@ -5,7 +5,7 @@ $:.unshift lib unless $:.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "postgres-copy"
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.6.1"
|
9
9
|
s.platform = Gem::Platform::RUBY
|
10
10
|
s.required_ruby_version = ">= 1.9.3"
|
11
11
|
s.authors = ["Diogo Biazus"]
|
@@ -22,7 +22,6 @@ Gem::Specification.new do |s|
|
|
22
22
|
|
23
23
|
s.add_dependency "pg", ">= 0.17"
|
24
24
|
s.add_dependency "activerecord", '>= 5.1'
|
25
|
-
s.add_dependency "responders"
|
26
25
|
s.add_development_dependency "bundler"
|
27
26
|
s.add_development_dependency "rdoc"
|
28
27
|
s.add_development_dependency "rspec", "~> 2.12"
|
data/spec/copy_from_spec.rb
CHANGED
@@ -14,6 +14,12 @@ describe "COPY FROM" do
|
|
14
14
|
TestModel.order(:id).map{|r| r.attributes}.should == [{'id' => 1, 'data' => 'test data 1'}]
|
15
15
|
end
|
16
16
|
|
17
|
+
it "should import from file if path is with a field_map" do
|
18
|
+
TestModel.copy_from File.expand_path('spec/fixtures/comma_with_header_to_map.csv'), map: {'ref' => 'id'}
|
19
|
+
TestModel.order(:id).map{|r| r.attributes}.should == [{'id' => 1, 'data' => 'test data 1'}]
|
20
|
+
end
|
21
|
+
|
22
|
+
|
17
23
|
it "should import from IO without field_map" do
|
18
24
|
TestModel.copy_from File.open(File.expand_path('spec/fixtures/comma_with_header.csv'), 'r')
|
19
25
|
TestModel.order(:id).map{|r| r.attributes}.should == [{'id' => 1, 'data' => 'test data 1'}]
|
@@ -173,4 +179,10 @@ describe "COPY FROM" do
|
|
173
179
|
TestModel.order(:id).first.attributes.should == {'id' => 1, 'data' => 'changed this data'}
|
174
180
|
TestModel.count.should == 2
|
175
181
|
end
|
182
|
+
|
183
|
+
it "should import csv headers with BOM when provided encoding option" do
|
184
|
+
TestModel.copy_from File.expand_path("spec/fixtures/comma_with_bom.csv"), :encoding => "bom|utf-8"
|
185
|
+
TestModel.order(:id).map{|r| r.attributes}.should == [{'id' => 1, 'data' => 'test data 1'}]
|
186
|
+
end
|
187
|
+
|
176
188
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: postgres-copy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Diogo Biazus
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '5.1'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: responders
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: bundler
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -134,12 +120,14 @@ files:
|
|
134
120
|
- spec/copy_to_spec.rb
|
135
121
|
- spec/fixtures/2_col_binary_data.dat
|
136
122
|
- spec/fixtures/comma_inside_field.csv
|
123
|
+
- spec/fixtures/comma_with_bom.csv
|
137
124
|
- spec/fixtures/comma_with_carriage_returns.csv
|
138
125
|
- spec/fixtures/comma_with_empty_string.csv
|
139
126
|
- spec/fixtures/comma_with_header.csv
|
140
127
|
- spec/fixtures/comma_with_header_and_scope.csv
|
141
128
|
- spec/fixtures/comma_with_header_empty_values_at_the_end.csv
|
142
129
|
- spec/fixtures/comma_with_header_multi.csv
|
130
|
+
- spec/fixtures/comma_with_header_to_map.csv
|
143
131
|
- spec/fixtures/comma_without_header.csv
|
144
132
|
- spec/fixtures/extra_field.rb
|
145
133
|
- spec/fixtures/reserved_word_model.rb
|
@@ -179,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
179
167
|
- !ruby/object:Gem::Version
|
180
168
|
version: '0'
|
181
169
|
requirements: []
|
182
|
-
rubygems_version: 3.1.
|
170
|
+
rubygems_version: 3.1.6
|
183
171
|
signing_key:
|
184
172
|
specification_version: 4
|
185
173
|
summary: Put COPY command functionality in ActiveRecord's model class
|