postgres-copy 1.4.0 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d64b9718c2f756ad9c55bb61a173ee66b0ed5f7
4
- data.tar.gz: b8a084b47fa7136bce031104d11b873482e13071
3
+ metadata.gz: 6477dfff9506950fc1f3a728138a48ce5f669a0c
4
+ data.tar.gz: 6a048abf7e41bbec754e4603b6f0fce48c6c3aa7
5
5
  SHA512:
6
- metadata.gz: d8b2b7d20479b9bc5e63a50d2c2ee256f26da73e3baf7d526e7f7976ca61684e022c62e2034acffeeb82ec184e1195c12f08940bb78def6dad9af29c068d558c
7
- data.tar.gz: 865261adbe21c5e16d2c928336b99b2e21bc49f5dd0025d49b3edeb89eccaff38f55a5af2ed6ed52e4ff0e01017c975d63ee8ebccebd41b44e4bb2ad2506e9d2
6
+ metadata.gz: 29f73c848994f32475f6652fe07788180efa8ab3faede9e98bc4d13d1f5afd9a95d165c2c8eb9c077fa9c8780aab876c167b1aa0fef49875b4a27c554785ee61
7
+ data.tar.gz: dba63f2014d5caad8e5f3623e85abf684f97ed8fd6ccee207f10033a4b090d2fa469d401b61173e1d0967988bc2e370434dee13b33525a863c35f864c0bdb987
@@ -2,6 +2,12 @@ language: ruby
2
2
  rvm:
3
3
  - 2.3.1
4
4
 
5
+ services:
6
+ - postgresql
7
+
8
+ addons:
9
+ postgresql: '9.4'
10
+
5
11
  branches:
6
12
  only:
7
13
  - master
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- postgres-copy (1.4.0)
4
+ postgres-copy (1.4.1)
5
5
  activerecord (>= 5.1)
6
6
  pg (>= 0.17)
7
7
  responders
@@ -9,63 +9,66 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- actionpack (5.1.4)
13
- actionview (= 5.1.4)
14
- activesupport (= 5.1.4)
12
+ actionpack (5.2.2)
13
+ actionview (= 5.2.2)
14
+ activesupport (= 5.2.2)
15
15
  rack (~> 2.0)
16
16
  rack-test (>= 0.6.3)
17
17
  rails-dom-testing (~> 2.0)
18
18
  rails-html-sanitizer (~> 1.0, >= 1.0.2)
19
- actionview (5.1.4)
20
- activesupport (= 5.1.4)
19
+ actionview (5.2.2)
20
+ activesupport (= 5.2.2)
21
21
  builder (~> 3.1)
22
22
  erubi (~> 1.4)
23
23
  rails-dom-testing (~> 2.0)
24
24
  rails-html-sanitizer (~> 1.0, >= 1.0.3)
25
- activemodel (5.1.4)
26
- activesupport (= 5.1.4)
27
- activerecord (5.1.4)
28
- activemodel (= 5.1.4)
29
- activesupport (= 5.1.4)
30
- arel (~> 8.0)
31
- activesupport (5.1.4)
25
+ activemodel (5.2.2)
26
+ activesupport (= 5.2.2)
27
+ activerecord (5.2.2)
28
+ activemodel (= 5.2.2)
29
+ activesupport (= 5.2.2)
30
+ arel (>= 9.0)
31
+ activesupport (5.2.2)
32
32
  concurrent-ruby (~> 1.0, >= 1.0.2)
33
- i18n (~> 0.7)
33
+ i18n (>= 0.7, < 2)
34
34
  minitest (~> 5.1)
35
35
  tzinfo (~> 1.1)
36
- arel (8.0.0)
36
+ arel (9.0.0)
37
37
  builder (3.2.3)
38
- concurrent-ruby (1.0.5)
38
+ concurrent-ruby (1.1.4)
39
+ crass (1.0.4)
39
40
  diff-lcs (1.3)
40
- erubi (1.6.1)
41
- i18n (0.8.6)
42
- loofah (2.0.3)
41
+ erubi (1.8.0)
42
+ i18n (1.5.3)
43
+ concurrent-ruby (~> 1.0)
44
+ loofah (2.2.3)
45
+ crass (~> 1.0.2)
43
46
  nokogiri (>= 1.5.9)
44
- method_source (0.8.2)
45
- mini_portile2 (2.3.0)
46
- minitest (5.10.3)
47
- nokogiri (1.8.1)
48
- mini_portile2 (~> 2.3.0)
49
- pg (0.21.0)
50
- rack (2.0.3)
51
- rack-test (0.7.0)
47
+ method_source (0.9.2)
48
+ mini_portile2 (2.4.0)
49
+ minitest (5.11.3)
50
+ nokogiri (1.10.1)
51
+ mini_portile2 (~> 2.4.0)
52
+ pg (1.1.4)
53
+ rack (2.0.6)
54
+ rack-test (1.1.0)
52
55
  rack (>= 1.0, < 3)
53
56
  rails-dom-testing (2.0.3)
54
57
  activesupport (>= 4.2.0)
55
58
  nokogiri (>= 1.6)
56
- rails-html-sanitizer (1.0.3)
57
- loofah (~> 2.0)
58
- railties (5.1.4)
59
- actionpack (= 5.1.4)
60
- activesupport (= 5.1.4)
59
+ rails-html-sanitizer (1.0.4)
60
+ loofah (~> 2.2, >= 2.2.2)
61
+ railties (5.2.2)
62
+ actionpack (= 5.2.2)
63
+ activesupport (= 5.2.2)
61
64
  method_source
62
65
  rake (>= 0.8.7)
63
- thor (>= 0.18.1, < 2.0)
66
+ thor (>= 0.19.0, < 2.0)
64
67
  rake (11.2.2)
65
68
  rdoc (5.0.0)
66
- responders (2.4.0)
67
- actionpack (>= 4.2.0, < 5.3)
68
- railties (>= 4.2.0, < 5.3)
69
+ responders (2.4.1)
70
+ actionpack (>= 4.2.0, < 6.0)
71
+ railties (>= 4.2.0, < 6.0)
69
72
  rspec (2.99.0)
70
73
  rspec-core (~> 2.99.0)
71
74
  rspec-expectations (~> 2.99.0)
@@ -74,9 +77,9 @@ GEM
74
77
  rspec-expectations (2.99.2)
75
78
  diff-lcs (>= 1.1.3, < 2.0)
76
79
  rspec-mocks (2.99.4)
77
- thor (0.20.0)
80
+ thor (0.20.3)
78
81
  thread_safe (0.3.6)
79
- tzinfo (1.2.3)
82
+ tzinfo (1.2.5)
80
83
  thread_safe (~> 0.1)
81
84
 
82
85
  PLATFORMS
@@ -90,4 +93,4 @@ DEPENDENCIES
90
93
  rspec (~> 2.12)
91
94
 
92
95
  BUNDLED WITH
93
- 1.14.6
96
+ 1.16.3
data/README.md CHANGED
@@ -55,8 +55,8 @@ This will execute in the database the command:
55
55
  COPY (SELECT "users".* FROM "users" ) TO '/tmp/users.csv' WITH DELIMITER ',' CSV HEADER
56
56
  ```
57
57
 
58
- Remark that the file will be created in the database server disk.
59
- But what if you want to write the lines in a file on the server that is running Rails, instead of the database?
58
+ Remark that the file will be created in the database server disk.
59
+ But what if you want to write the lines in a file on the server that is running Rails, instead of the database?
60
60
  In this case you can pass a block and retrieve the generated lines and then write them to a file:
61
61
 
62
62
  ```ruby
@@ -166,6 +166,12 @@ To specify NULL value you can pass the null option parameter.
166
166
  User.copy_from "/tmp/users.csv", :null => 'null'
167
167
  ```
168
168
 
169
+ Match the specified columns' values against the null string, even if it has been quoted, and if a match is found set the value to NULL (Postgres 9.4+ only).
170
+
171
+ ```ruby
172
+ User.copy_from "/tmp/users.csv", :null => '', :force_null => [:name, :city]
173
+ ```
174
+
169
175
 
170
176
  To copy a binary formatted data file or IO object you can specify the format as binary
171
177
 
@@ -77,8 +77,9 @@ module PostgresCopy
77
77
  "BINARY"
78
78
  else
79
79
  quote = options[:quote] == "'" ? "''" : options[:quote]
80
- null = options.key?(:null) ? "NULL '#{options[:null]}'" : ''
81
- "DELIMITER '#{options[:delimiter]}' QUOTE '#{quote}' #{null} CSV"
80
+ null = options.key?(:null) ? "NULL '#{options[:null]}'" : nil
81
+ force_null = options.key?(:force_null) ? "FORCE_NULL(#{options[:force_null].join(',')})" : nil
82
+ "WITH (" + ["DELIMITER '#{options[:delimiter]}'", "QUOTE '#{quote}'", null, force_null, "FORMAT CSV"].compact.join(', ') + ")"
82
83
  end
83
84
  io = path_or_io.instance_of?(String) ? File.open(path_or_io, 'r') : path_or_io
84
85
 
@@ -110,15 +111,31 @@ module PostgresCopy
110
111
  rescue EOFError
111
112
  end
112
113
  else
114
+ line_buffer = ''
115
+
113
116
  while line = io.gets do
114
117
  next if line.strip.size == 0
115
- if block_given?
116
- row = CSV.parse_line(line.strip, {:col_sep => options[:delimiter]})
117
- yield(row)
118
- next if row.all?{|f| f.nil? }
119
- line = CSV.generate_line(row, {:col_sep => options[:delimiter]})
118
+
119
+ line_buffer += line
120
+
121
+ # If line is incomplete, get the next line until it terminates
122
+ if line_buffer =~ /\n$/ || line_buffer =~ /\Z/
123
+ if block_given?
124
+ begin
125
+ row = CSV.parse_line(line_buffer.strip, {:col_sep => options[:delimiter]})
126
+ yield(row)
127
+ next if row.all?{|f| f.nil? }
128
+ line_buffer = CSV.generate_line(row, {:col_sep => options[:delimiter]})
129
+ rescue CSV::MalformedCSVError
130
+ next
131
+ end
132
+ end
133
+
134
+ connection.raw_connection.put_copy_data(line_buffer)
135
+
136
+ # Clear the buffer
137
+ line_buffer = ''
120
138
  end
121
- connection.raw_connection.put_copy_data line
122
139
  end
123
140
  end
124
141
  end
@@ -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.4.0"
8
+ s.version = "1.4.1"
9
9
  s.platform = Gem::Platform::RUBY
10
10
  s.required_ruby_version = ">= 1.9.3"
11
11
  s.authors = ["Diogo Biazus"]
@@ -100,20 +100,20 @@ describe "COPY FROM" do
100
100
  ReservedWordModel.copy_from File.expand_path('spec/fixtures/reserved_words.csv'), :delimiter => "\t"
101
101
  ReservedWordModel.order(:id).map{|r| r.attributes}.should == [{"group"=>"group name", "id"=>1, "select"=>"test select"}]
102
102
  end
103
-
103
+
104
104
  it "should import even last columns have empty values" do
105
105
  TestExtendedModel.copy_from File.expand_path('spec/fixtures/comma_with_header_empty_values_at_the_end.csv')
106
- TestExtendedModel.order(:id).map{|r| r.attributes}.should ==
106
+ TestExtendedModel.order(:id).map{|r| r.attributes}.should ==
107
107
  [{"id"=>1, "data"=>"test data 1", "more_data"=>nil, "other_data"=>nil, "final_data"=>nil},
108
108
  {"id"=>2, "data"=>"test data 2", "more_data"=>"9", "other_data"=>nil, "final_data"=>nil},
109
109
  {"id"=>3, "data"=>"test data 2", "more_data"=>"9", "other_data"=>nil, "final_data"=>"0"}]
110
110
  end
111
-
111
+
112
112
  it "should import even last columns have empty values with block" do
113
113
  TestExtendedModel.copy_from File.expand_path('spec/fixtures/comma_with_header_empty_values_at_the_end.csv') do |row|
114
114
  row[4]="666"
115
115
  end
116
- TestExtendedModel.order(:id).map{|r| r.attributes}.should ==
116
+ TestExtendedModel.order(:id).map{|r| r.attributes}.should ==
117
117
  [{"id"=>1, "data"=>"test data 1", "more_data"=>nil, "other_data"=>nil, "final_data"=>"666"},
118
118
  {"id"=>2, "data"=>"test data 2", "more_data"=>"9", "other_data"=>nil, "final_data"=>"666"},
119
119
  {"id"=>3, "data"=>"test data 2", "more_data"=>"9", "other_data"=>nil, "final_data"=>"666"}]
@@ -150,4 +150,14 @@ describe "COPY FROM" do
150
150
  TestModel.copy_from File.open(File.expand_path('spec/fixtures/special_null_with_header.csv'), 'r'), :null => 'NULL'
151
151
  TestModel.order(:id).map{|r| r.attributes}.should == [{'id' => 1, 'data' => nil}]
152
152
  end
153
+
154
+ it "should import with a carriage return in the value" do
155
+ TestModel.copy_from File.expand_path('spec/fixtures/comma_with_carriage_returns.csv')
156
+ TestModel.order(:id).map{|r| r.attributes}.should == [{'id' => 1, 'data' => "test\ndata 1"}]
157
+ end
158
+
159
+ it "should import custom force null expressions from path" do
160
+ TestModel.copy_from File.expand_path('spec/fixtures/comma_with_empty_string.csv'), :null => '', :force_null => [:data]
161
+ TestModel.order(:id).map{|r| r.attributes}.should == [{'id' => 1, 'data' => nil}]
162
+ end
153
163
  end
@@ -0,0 +1,3 @@
1
+ id,data
2
+ 1,"test
3
+ data 1"
@@ -0,0 +1,2 @@
1
+ id,data
2
+ 1,""
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.0
4
+ version: 1.4.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: 2018-01-28 00:00:00.000000000 Z
11
+ date: 2019-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -124,7 +124,6 @@ files:
124
124
  - LICENSE
125
125
  - README.md
126
126
  - Rakefile
127
- - VERSION
128
127
  - lib/postgres-copy.rb
129
128
  - lib/postgres-copy/acts_as_copy_target.rb
130
129
  - lib/postgres-copy/csv_responder.rb
@@ -135,6 +134,8 @@ files:
135
134
  - spec/copy_to_spec.rb
136
135
  - spec/fixtures/2_col_binary_data.dat
137
136
  - spec/fixtures/comma_inside_field.csv
137
+ - spec/fixtures/comma_with_carriage_returns.csv
138
+ - spec/fixtures/comma_with_empty_string.csv
138
139
  - spec/fixtures/comma_with_header.csv
139
140
  - spec/fixtures/comma_with_header_and_scope.csv
140
141
  - spec/fixtures/comma_with_header_empty_values_at_the_end.csv
@@ -177,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
178
  version: '0'
178
179
  requirements: []
179
180
  rubyforge_project:
180
- rubygems_version: 2.6.8
181
+ rubygems_version: 2.6.13
181
182
  signing_key:
182
183
  specification_version: 4
183
184
  summary: Put COPY command functionality in ActiveRecord's model class
@@ -188,6 +189,8 @@ test_files:
188
189
  - spec/copy_to_spec.rb
189
190
  - spec/fixtures/2_col_binary_data.dat
190
191
  - spec/fixtures/comma_inside_field.csv
192
+ - spec/fixtures/comma_with_carriage_returns.csv
193
+ - spec/fixtures/comma_with_empty_string.csv
191
194
  - spec/fixtures/comma_with_header.csv
192
195
  - spec/fixtures/comma_with_header_and_scope.csv
193
196
  - spec/fixtures/comma_with_header_empty_values_at_the_end.csv
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.5.6