activerecord-copy 1.0.0
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 +7 -0
- data/.gitignore +17 -0
- data/.rubocop.yml +40 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +49 -0
- data/README.md +40 -0
- data/Rakefile +1 -0
- data/activerecord-copy.gemspec +25 -0
- data/lib/activerecord-copy.rb +92 -0
- data/lib/activerecord-copy/constants.rb +18 -0
- data/lib/activerecord-copy/decoder.rb +176 -0
- data/lib/activerecord-copy/encode_for_copy.rb +253 -0
- data/lib/activerecord-copy/exception.rb +4 -0
- data/lib/activerecord-copy/temp_buffer.rb +38 -0
- data/lib/activerecord-copy/version.rb +3 -0
- data/spec/big_write_spec.rb +17 -0
- data/spec/errors_spec.rb +8 -0
- data/spec/fixtures/3_col_array.txt +1 -0
- data/spec/fixtures/3_col_hstore.dat +0 -0
- data/spec/fixtures/3_col_hstore.txt +1 -0
- data/spec/fixtures/3_column_array.dat +0 -0
- data/spec/fixtures/array_with_two.dat +0 -0
- data/spec/fixtures/array_with_two2.dat +0 -0
- data/spec/fixtures/big_str_array.dat +0 -0
- data/spec/fixtures/big_str_array2.dat +0 -0
- data/spec/fixtures/bigint.dat +0 -0
- data/spec/fixtures/date.dat +0 -0
- data/spec/fixtures/date2.dat +0 -0
- data/spec/fixtures/date2000.dat +0 -0
- data/spec/fixtures/dates.dat +0 -0
- data/spec/fixtures/dates_p924.dat +0 -0
- data/spec/fixtures/dates_pg935.dat +0 -0
- data/spec/fixtures/empty_uuid.dat +0 -0
- data/spec/fixtures/falseclass.dat +0 -0
- data/spec/fixtures/float.dat +0 -0
- data/spec/fixtures/hstore_utf8.dat +0 -0
- data/spec/fixtures/intarray.dat +0 -0
- data/spec/fixtures/json.dat +0 -0
- data/spec/fixtures/json_array.dat +0 -0
- data/spec/fixtures/just_an_array.dat +0 -0
- data/spec/fixtures/just_an_array2.dat +0 -0
- data/spec/fixtures/multiline_hstore.dat +0 -0
- data/spec/fixtures/output.dat +0 -0
- data/spec/fixtures/timestamp.dat +0 -0
- data/spec/fixtures/timestamp_9.3.dat +0 -0
- data/spec/fixtures/timestamp_big.dat +0 -0
- data/spec/fixtures/timestamp_rounding.dat +0 -0
- data/spec/fixtures/trueclass.dat +0 -0
- data/spec/fixtures/utf8.dat +0 -0
- data/spec/fixtures/uuid.dat +0 -0
- data/spec/fixtures/uuid_array.dat +0 -0
- data/spec/multiline_spec.rb +17 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/verify_data_formats_spec.rb +415 -0
- data/spec/verify_decoder_spec.rb +263 -0
- metadata +182 -0
@@ -0,0 +1,415 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
describe 'generating data' do
|
6
|
+
it 'encodes hstore data correctly' do
|
7
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
8
|
+
encoder.add [1, 'text', { a: 1, b: 'asdf' }]
|
9
|
+
encoder.close
|
10
|
+
io = encoder.get_io
|
11
|
+
existing_data = filedata('3_col_hstore.dat')
|
12
|
+
str = io.read
|
13
|
+
expect(io.class.name).to eq 'StringIO'
|
14
|
+
str.force_encoding('ASCII-8BIT')
|
15
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
16
|
+
expect(str).to eq existing_data
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'encodes hstore data correctly from tempfile' do
|
20
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true)
|
21
|
+
encoder.add [1, 'text', { a: 1, b: 'asdf' }]
|
22
|
+
encoder.close
|
23
|
+
io = encoder.get_io
|
24
|
+
existing_data = filedata('3_col_hstore.dat')
|
25
|
+
str = io.read
|
26
|
+
expect(io.class.name).to eq 'Tempfile'
|
27
|
+
str.force_encoding('ASCII-8BIT')
|
28
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
29
|
+
expect(str).to eq existing_data
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'encodes hstore with utf8 data correctly from tempfile' do
|
33
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true)
|
34
|
+
encoder.add [{ test: 'Ekström' }]
|
35
|
+
encoder.add [{ test: 'Dueñas' }]
|
36
|
+
encoder.add [{ 'account_first_name' => 'asdfasdf asñas', 'testtesttesttesttesttestest' => '', 'aasdfasdfasdfasdfasdfasdfasdfasdfasfasfasdfs' => '' }] # needed to verify encoding issue
|
37
|
+
encoder.close
|
38
|
+
io = encoder.get_io
|
39
|
+
existing_data = filedata('hstore_utf8.dat')
|
40
|
+
str = io.read
|
41
|
+
expect(io.class.name).to eq 'Tempfile'
|
42
|
+
str.force_encoding('ASCII-8BIT')
|
43
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
44
|
+
expect(str).to eq existing_data
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'encodes TrueClass data correctly' do
|
48
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
49
|
+
encoder.add [true]
|
50
|
+
encoder.close
|
51
|
+
io = encoder.get_io
|
52
|
+
existing_data = filedata('trueclass.dat')
|
53
|
+
str = io.read
|
54
|
+
expect(io.class.name).to eq 'StringIO'
|
55
|
+
str.force_encoding('ASCII-8BIT')
|
56
|
+
expect(str).to eq existing_data
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'encodes FalseClass data correctly' do
|
60
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
61
|
+
encoder.add [false]
|
62
|
+
encoder.close
|
63
|
+
io = encoder.get_io
|
64
|
+
existing_data = filedata('falseclass.dat')
|
65
|
+
str = io.read
|
66
|
+
expect(io.class.name).to eq 'StringIO'
|
67
|
+
str.force_encoding('ASCII-8BIT')
|
68
|
+
expect(str).to eq existing_data
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'encodes array data correctly' do
|
72
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
73
|
+
encoder.add [%w(hi jim)]
|
74
|
+
encoder.close
|
75
|
+
io = encoder.get_io
|
76
|
+
existing_data = filedata('array_with_two2.dat')
|
77
|
+
str = io.read
|
78
|
+
expect(io.class.name).to eq 'StringIO'
|
79
|
+
str.force_encoding('ASCII-8BIT')
|
80
|
+
expect(str).to eq existing_data
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'encodes string array data correctly' do
|
84
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
85
|
+
encoder.add [%w(asdfasdfasdfasdf asdfasdfasdfasdfadsfadf 1123423423423)]
|
86
|
+
encoder.close
|
87
|
+
io = encoder.get_io
|
88
|
+
existing_data = filedata('big_str_array.dat')
|
89
|
+
str = io.read
|
90
|
+
expect(io.class.name).to eq 'StringIO'
|
91
|
+
str.force_encoding('ASCII-8BIT')
|
92
|
+
expect(str).to eq existing_data
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'encodes string array with big string int' do
|
96
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
97
|
+
encoder.add [['182749082739172']]
|
98
|
+
encoder.close
|
99
|
+
io = encoder.get_io
|
100
|
+
existing_data = filedata('just_an_array2.dat')
|
101
|
+
str = io.read
|
102
|
+
expect(io.class.name).to eq 'StringIO'
|
103
|
+
str.force_encoding('ASCII-8BIT')
|
104
|
+
expect(str).to eq existing_data
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'encodes string array data correctly' do
|
108
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
109
|
+
encoder.add [%w(asdfasdfasdfasdf asdfasdfasdfasdfadsfadf)]
|
110
|
+
encoder.close
|
111
|
+
io = encoder.get_io
|
112
|
+
existing_data = filedata('big_str_array2.dat')
|
113
|
+
str = io.read
|
114
|
+
expect(io.class.name).to eq 'StringIO'
|
115
|
+
str.force_encoding('ASCII-8BIT')
|
116
|
+
expect(str).to eq existing_data
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'encodes array data from tempfile correctly', pending: 'broken right now' do
|
120
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true)
|
121
|
+
encoder.add [1, 'hi', ['hi', 'there', 'rubyist']]
|
122
|
+
encoder.close
|
123
|
+
io = encoder.get_io
|
124
|
+
existing_data = filedata('3_column_array.dat')
|
125
|
+
str = io.read
|
126
|
+
expect(io.class.name).to eq 'Tempfile'
|
127
|
+
str.force_encoding('ASCII-8BIT')
|
128
|
+
expect(str).to eq existing_data
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'encodes integer array data from tempfile correctly' do
|
132
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true)
|
133
|
+
encoder.add [[1, 2, 3]]
|
134
|
+
encoder.close
|
135
|
+
io = encoder.get_io
|
136
|
+
existing_data = filedata('intarray.dat')
|
137
|
+
str = io.read
|
138
|
+
expect(io.class.name).to eq 'Tempfile'
|
139
|
+
str.force_encoding('ASCII-8BIT')
|
140
|
+
expect(str).to eq existing_data
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'encodes date data correctly' do
|
144
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
145
|
+
encoder.add [Date.parse('1900-12-03')]
|
146
|
+
encoder.close
|
147
|
+
io = encoder.get_io
|
148
|
+
existing_data = filedata('date.dat')
|
149
|
+
str = io.read
|
150
|
+
expect(io.class.name).to eq 'StringIO'
|
151
|
+
str.force_encoding('ASCII-8BIT')
|
152
|
+
expect(str).to eq existing_data
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'encodes date data correctly for years > 2000' do
|
156
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
157
|
+
encoder.add [Date.parse('2033-01-12')]
|
158
|
+
encoder.close
|
159
|
+
io = encoder.get_io
|
160
|
+
existing_data = filedata('date2000.dat')
|
161
|
+
str = io.read
|
162
|
+
expect(io.class.name).to eq 'StringIO'
|
163
|
+
str.force_encoding('ASCII-8BIT')
|
164
|
+
expect(str).to eq existing_data
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'encodes date data correctly in the 70s' do
|
168
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
169
|
+
encoder.add [Date.parse('1971-12-11')]
|
170
|
+
encoder.close
|
171
|
+
io = encoder.get_io
|
172
|
+
existing_data = filedata('date2.dat')
|
173
|
+
str = io.read
|
174
|
+
expect(io.class.name).to eq 'StringIO'
|
175
|
+
str.force_encoding('ASCII-8BIT')
|
176
|
+
expect(str).to eq existing_data
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'encodes multiple 2015 dates' do
|
180
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
181
|
+
encoder.add [Date.parse('2015-04-08'), nil, Date.parse('2015-04-13')]
|
182
|
+
encoder.close
|
183
|
+
io = encoder.get_io
|
184
|
+
existing_data = filedata('dates.dat')
|
185
|
+
str = io.read
|
186
|
+
expect(io.class.name).to eq 'StringIO'
|
187
|
+
str.force_encoding('ASCII-8BIT')
|
188
|
+
expect(str).to eq existing_data
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'encodes timestamp data correctly' do
|
192
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
193
|
+
encoder.add [Time.parse('2013-06-11 15:03:54.62605 UTC')]
|
194
|
+
encoder.close
|
195
|
+
io = encoder.get_io
|
196
|
+
existing_data = filedata('timestamp.dat')
|
197
|
+
str = io.read
|
198
|
+
expect(io.class.name).to eq 'StringIO'
|
199
|
+
str.force_encoding('ASCII-8BIT')
|
200
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
201
|
+
expect(str).to eq existing_data
|
202
|
+
end
|
203
|
+
|
204
|
+
require 'time'
|
205
|
+
|
206
|
+
# When this timestamp is converted to float it will incorrectly change the
|
207
|
+
# last digit of usecs to and therefore insert the wrong data into the database
|
208
|
+
it 'encodes timestamp data correctly without rounding' do
|
209
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
210
|
+
encoder.add [Time.parse('2017-07-23 00:02:57.121215 UTC')]
|
211
|
+
encoder.close
|
212
|
+
io = encoder.get_io
|
213
|
+
existing_data = filedata('timestamp_rounding.dat')
|
214
|
+
str = io.read
|
215
|
+
expect(io.class.name).to eq 'StringIO'
|
216
|
+
str.force_encoding('ASCII-8BIT')
|
217
|
+
# File.open('spec/fixtures/timestamp_rounding.dat', 'w:ASCII-8BIT') { |out| out.write(str) }
|
218
|
+
expect(str).to eq existing_data
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'encodes dates and times in pg 9.2.4' do
|
222
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
223
|
+
encoder.add [Date.parse('2015-04-08'), nil, Time.parse('2015-02-13 16:13:57.732772 UTC')]
|
224
|
+
encoder.close
|
225
|
+
io = encoder.get_io
|
226
|
+
existing_data = filedata('dates_p924.dat')
|
227
|
+
str = io.read
|
228
|
+
expect(io.class.name).to eq 'StringIO'
|
229
|
+
str.force_encoding('ASCII-8BIT')
|
230
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
231
|
+
expect(str).to eq existing_data
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'encodes dates and times in pg 9.3.5' do
|
235
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
236
|
+
encoder.add [Date.parse('2015-04-08'), nil, Time.parse('2015-02-13 16:13:57.732772 UTC')]
|
237
|
+
encoder.close
|
238
|
+
io = encoder.get_io
|
239
|
+
existing_data = filedata('dates_pg935.dat')
|
240
|
+
str = io.read
|
241
|
+
expect(io.class.name).to eq 'StringIO'
|
242
|
+
str.force_encoding('ASCII-8BIT')
|
243
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
244
|
+
expect(str).to eq existing_data
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'encodes timestamp data correctly' do
|
248
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
249
|
+
encoder.add [Time.parse('2013-06-11 15:03:54.62605 UTC')]
|
250
|
+
encoder.close
|
251
|
+
io = encoder.get_io
|
252
|
+
existing_data = filedata('timestamp.dat')
|
253
|
+
str = io.read
|
254
|
+
expect(io.class.name).to eq 'StringIO'
|
255
|
+
str.force_encoding('ASCII-8BIT')
|
256
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
257
|
+
expect(str).to eq existing_data
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'encodes big timestamp data correctly' do
|
261
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
262
|
+
encoder.add [Time.parse('2014-12-02 16:01:22.437311 UTC')]
|
263
|
+
encoder.close
|
264
|
+
io = encoder.get_io
|
265
|
+
existing_data = filedata('timestamp_9.3.dat')
|
266
|
+
str = io.read
|
267
|
+
expect(io.class.name).to eq 'StringIO'
|
268
|
+
str.force_encoding('ASCII-8BIT')
|
269
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
270
|
+
expect(str).to eq existing_data
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'encodes json hash correctly' do
|
274
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(column_types: { 0 => :json })
|
275
|
+
encoder.add [{}]
|
276
|
+
encoder.close
|
277
|
+
io = encoder.get_io
|
278
|
+
existing_data = filedata('json.dat')
|
279
|
+
str = io.read
|
280
|
+
expect(io.class.name).to eq 'StringIO'
|
281
|
+
str.force_encoding('ASCII-8BIT')
|
282
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
283
|
+
expect(str).to eq existing_data
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'encodes json array correctly' do
|
287
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(column_types: { 0 => :json })
|
288
|
+
encoder.add [[]]
|
289
|
+
encoder.close
|
290
|
+
io = encoder.get_io
|
291
|
+
existing_data = filedata('json_array.dat')
|
292
|
+
str = io.read
|
293
|
+
expect(io.class.name).to eq 'StringIO'
|
294
|
+
str.force_encoding('ASCII-8BIT')
|
295
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
296
|
+
expect(str).to eq existing_data
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'encodes float correctly from tempfile' do
|
300
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true)
|
301
|
+
encoder.add [Time.parse('2013-06-11 15:03:54.62605 UTC')]
|
302
|
+
encoder.close
|
303
|
+
io = encoder.get_io
|
304
|
+
existing_data = filedata('timestamp.dat')
|
305
|
+
str = io.read
|
306
|
+
expect(io.class.name).to eq 'Tempfile'
|
307
|
+
str.force_encoding('ASCII-8BIT')
|
308
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
309
|
+
expect(str).to eq existing_data
|
310
|
+
end
|
311
|
+
|
312
|
+
it 'encodes float data correctly' do
|
313
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
314
|
+
encoder.add [1_234_567.1234567]
|
315
|
+
encoder.close
|
316
|
+
io = encoder.get_io
|
317
|
+
existing_data = filedata('float.dat')
|
318
|
+
str = io.read
|
319
|
+
expect(io.class.name).to eq 'StringIO'
|
320
|
+
str.force_encoding('ASCII-8BIT')
|
321
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
322
|
+
expect(str).to eq existing_data
|
323
|
+
end
|
324
|
+
|
325
|
+
it 'encode float correctly from tempfile' do
|
326
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true)
|
327
|
+
encoder.add [1_234_567.1234567]
|
328
|
+
encoder.close
|
329
|
+
io = encoder.get_io
|
330
|
+
existing_data = filedata('float.dat')
|
331
|
+
str = io.read
|
332
|
+
expect(io.class.name).to eq 'Tempfile'
|
333
|
+
str.force_encoding('ASCII-8BIT')
|
334
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
335
|
+
expect(str).to eq existing_data
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'encodes uuid correctly from tempfile' do
|
339
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true, column_types: { 0 => :uuid })
|
340
|
+
encoder.add ['e876eef5-a116-4a27-b71f-bac4a1dcd20e']
|
341
|
+
encoder.close
|
342
|
+
io = encoder.get_io
|
343
|
+
existing_data = filedata('uuid.dat')
|
344
|
+
str = io.read
|
345
|
+
expect(io.class.name).to eq 'Tempfile'
|
346
|
+
str.force_encoding('ASCII-8BIT')
|
347
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
348
|
+
expect(str).to eq existing_data
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'encodes null uuid correctly from tempfile' do
|
352
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true, column_types: { 1 => :uuid })
|
353
|
+
encoder.add ['before2', nil, nil, 123_423_423]
|
354
|
+
encoder.close
|
355
|
+
io = encoder.get_io
|
356
|
+
existing_data = filedata('empty_uuid.dat')
|
357
|
+
str = io.read
|
358
|
+
expect(io.class.name).to eq 'Tempfile'
|
359
|
+
str.force_encoding('ASCII-8BIT')
|
360
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
361
|
+
expect(str).to eq existing_data
|
362
|
+
end
|
363
|
+
|
364
|
+
it 'encodes uuid correctly from tempfile' do
|
365
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true, column_types: { 0 => :uuid })
|
366
|
+
encoder.add [['6272bd7d-adae-44b7-bba1-dca871c2a6fd', '7dc8431f-fcce-4d4d-86f3-6857cba47d38']]
|
367
|
+
encoder.close
|
368
|
+
io = encoder.get_io
|
369
|
+
existing_data = filedata('uuid_array.dat')
|
370
|
+
str = io.read
|
371
|
+
expect(io.class.name).to eq 'Tempfile'
|
372
|
+
str.force_encoding('ASCII-8BIT')
|
373
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
374
|
+
expect(str).to eq existing_data
|
375
|
+
end
|
376
|
+
|
377
|
+
it 'encodes utf8 string correctly' do
|
378
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new
|
379
|
+
ekstrom = 'Ekström'
|
380
|
+
encoder.add [ekstrom]
|
381
|
+
encoder.close
|
382
|
+
io = encoder.get_io
|
383
|
+
existing_data = filedata('utf8.dat')
|
384
|
+
str = io.read
|
385
|
+
expect(io.class.name).to eq 'StringIO'
|
386
|
+
str.force_encoding('ASCII-8BIT')
|
387
|
+
expect(str).to eq existing_data
|
388
|
+
end
|
389
|
+
|
390
|
+
it 'encodes bigint as int correctly from tempfile' do
|
391
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true, column_types: { 0 => :bigint })
|
392
|
+
encoder.add [23_372_036_854_775_808, 'test']
|
393
|
+
encoder.close
|
394
|
+
io = encoder.get_io
|
395
|
+
existing_data = filedata('bigint.dat')
|
396
|
+
str = io.read
|
397
|
+
expect(io.class.name).to eq 'Tempfile'
|
398
|
+
str.force_encoding('ASCII-8BIT')
|
399
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
400
|
+
expect(str).to eq existing_data
|
401
|
+
end
|
402
|
+
|
403
|
+
it 'encodes bigint correctly from tempfile' do
|
404
|
+
encoder = ActiveRecordCopy::EncodeForCopy.new(use_tempfile: true, column_types: { 0 => :bigint })
|
405
|
+
encoder.add %w(23372036854775808 test)
|
406
|
+
encoder.close
|
407
|
+
io = encoder.get_io
|
408
|
+
existing_data = filedata('bigint.dat')
|
409
|
+
str = io.read
|
410
|
+
expect(io.class.name).to eq 'Tempfile'
|
411
|
+
str.force_encoding('ASCII-8BIT')
|
412
|
+
# File.open('spec/fixtures/output.dat', 'w:ASCII-8BIT') {|out| out.write(str) }
|
413
|
+
expect(str).to eq existing_data
|
414
|
+
end
|
415
|
+
end
|
@@ -0,0 +1,263 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
describe 'parsing data' do
|
6
|
+
it 'walks through each line and stop' do
|
7
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
8
|
+
io: fileio('hstore_utf8.dat'),
|
9
|
+
column_types: { 0 => :hstore }
|
10
|
+
)
|
11
|
+
lines = []
|
12
|
+
decoder.each do |l|
|
13
|
+
lines << l
|
14
|
+
end
|
15
|
+
expect(lines).to eq [
|
16
|
+
[{ 'test' => 'Ekström' }],
|
17
|
+
[{ 'test' => 'Dueñas' }],
|
18
|
+
[{ 'account_first_name' => 'asdfasdf asñas', 'testtesttesttesttesttestest' => '', 'aasdfasdfasdfasdfasdfasdfasdfasdfasfasfasdfs' => '' }]
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'handles getting called after running out of data' do
|
23
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
24
|
+
io: fileio('3_col_hstore.dat'),
|
25
|
+
column_types: { 0 => :int, 1 => :string, 2 => :hstore }
|
26
|
+
)
|
27
|
+
r = decoder.read_line
|
28
|
+
expect(r).to eq [1, 'text', { 'a' => '1', 'b' => 'asdf' }]
|
29
|
+
expect(decoder.read_line).to be_nil
|
30
|
+
expect(decoder.read_line).to be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'encodes hstore data correctly' do
|
34
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
35
|
+
io: fileio('3_col_hstore.dat'),
|
36
|
+
column_types: { 0 => :int, 1 => :string, 2 => :hstore }
|
37
|
+
)
|
38
|
+
r = decoder.read_line
|
39
|
+
expect(r).to eq [1, 'text', { 'a' => '1', 'b' => 'asdf' }]
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns nil if past data' do
|
43
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
44
|
+
io: fileio('3_col_hstore.dat'),
|
45
|
+
column_types: { 0 => :int, 1 => :string, 2 => :hstore }
|
46
|
+
)
|
47
|
+
r = decoder.read_line
|
48
|
+
expect(r).to eq [1, 'text', { 'a' => '1', 'b' => 'asdf' }]
|
49
|
+
r = decoder.read_line
|
50
|
+
expect(r).to eq nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'encodes hstore with utf8 data correctly from tempfile' do
|
54
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
55
|
+
io: fileio('hstore_utf8.dat'),
|
56
|
+
column_types: { 0 => :hstore }
|
57
|
+
)
|
58
|
+
r = decoder.read_line
|
59
|
+
expect(r).to eq [{ 'test' => 'Ekström' }]
|
60
|
+
r = decoder.read_line
|
61
|
+
expect(r).to eq [{ 'test' => 'Dueñas' }]
|
62
|
+
r = decoder.read_line
|
63
|
+
expect(r).to eq [{ 'account_first_name' => 'asdfasdf asñas', 'testtesttesttesttesttestest' => '', 'aasdfasdfasdfasdfasdfasdfasdfasdfasfasfasdfs' => '' }]
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'encodes TrueClass data correctly' do
|
67
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
68
|
+
io: fileio('trueclass.dat'),
|
69
|
+
column_types: { 0 => :boolean }
|
70
|
+
)
|
71
|
+
r = decoder.read_line
|
72
|
+
expect(r).to eq [true]
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'encodes FalseClass data correctly' do
|
76
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
77
|
+
io: fileio('falseclass.dat'),
|
78
|
+
column_types: { 0 => :boolean }
|
79
|
+
)
|
80
|
+
r = decoder.read_line
|
81
|
+
expect(r).to eq [false]
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'encodes array data correctly' do
|
85
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
86
|
+
io: fileio('array_with_two2.dat'),
|
87
|
+
column_types: { 0 => :array }
|
88
|
+
)
|
89
|
+
r = decoder.read_line
|
90
|
+
expect(r).to eq [%w(hi jim)]
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'encodes string array data correctly' do
|
94
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
95
|
+
io: fileio('big_str_array.dat'),
|
96
|
+
column_types: { 0 => :array }
|
97
|
+
)
|
98
|
+
r = decoder.read_line
|
99
|
+
expect(r).to eq [%w(asdfasdfasdfasdf asdfasdfasdfasdfadsfadf 1123423423423)]
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'encodes string array with big string int' do
|
103
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
104
|
+
io: fileio('just_an_array2.dat'),
|
105
|
+
column_types: { 0 => :array }
|
106
|
+
)
|
107
|
+
r = decoder.read_line
|
108
|
+
expect(r).to eq [['182749082739172']]
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'encodes string array data correctly' do
|
112
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
113
|
+
io: fileio('big_str_array2.dat'),
|
114
|
+
column_types: { 0 => :array }
|
115
|
+
)
|
116
|
+
r = decoder.read_line
|
117
|
+
expect(r).to eq [%w(asdfasdfasdfasdf asdfasdfasdfasdfadsfadf)]
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'encodes array data from tempfile correctly', pending: 'broken right now' do
|
121
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
122
|
+
io: fileio('3_column_array.dat'),
|
123
|
+
column_types: { 0 => :array }
|
124
|
+
)
|
125
|
+
r = decoder.read_line
|
126
|
+
expect(r).to eq [1, 'hi', ['hi', 'there', 'rubyist']]
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'encodes integer array data from tempfile correctly' do
|
130
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
131
|
+
io: fileio('intarray.dat'),
|
132
|
+
column_types: { 0 => :array }
|
133
|
+
)
|
134
|
+
r = decoder.read_line
|
135
|
+
expect(r).to eq [[1, 2, 3]]
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'encodes old date data correctly' do
|
139
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
140
|
+
io: fileio('date.dat'),
|
141
|
+
column_types: { 0 => :date }
|
142
|
+
)
|
143
|
+
r = decoder.read_line
|
144
|
+
expect(r).to eq [Date.parse('1900-12-03')]
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'encodes date data correctly for years > 2000' do
|
148
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
149
|
+
io: fileio('date2000.dat'),
|
150
|
+
column_types: { 0 => :date }
|
151
|
+
)
|
152
|
+
r = decoder.read_line
|
153
|
+
expect(r).to eq [Date.parse('2033-01-12')]
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'encodes date data correctly in the 70s' do
|
157
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
158
|
+
io: fileio('date2.dat'),
|
159
|
+
column_types: { 0 => :date }
|
160
|
+
)
|
161
|
+
r = decoder.read_line
|
162
|
+
expect(r).to eq [Date.parse('1971-12-11')]
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'encodes multiple 2015 dates' do
|
166
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
167
|
+
io: fileio('dates.dat'),
|
168
|
+
column_types: { 0 => :date, 1 => :date, 2 => :date }
|
169
|
+
)
|
170
|
+
r = decoder.read_line
|
171
|
+
expect(r).to eq [Date.parse('2015-04-08'), nil, Date.parse('2015-04-13')]
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'encodes timestamp data correctly' do
|
175
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
176
|
+
io: fileio('timestamp.dat'),
|
177
|
+
column_types: { 0 => :time }
|
178
|
+
)
|
179
|
+
r = decoder.read_line
|
180
|
+
expect(r.map(&:to_f)).to eq [Time.parse('2013-06-11 15:03:54.62605 UTC')].map(&:to_f)
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'encodes dates and times in pg 9.2.4' do
|
184
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
185
|
+
io: fileio('dates_p924.dat'),
|
186
|
+
column_types: { 0 => :date, 2 => :time }
|
187
|
+
)
|
188
|
+
r = decoder.read_line
|
189
|
+
expect(r.map { |f| f.is_a?(Time) ? f.to_f : f }).to eq [Date.parse('2015-04-08'), nil, Time.parse('2015-02-13 16:13:57.732772 UTC')].map { |f| f.is_a?(Time) ? f.to_f : f }
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'encodes dates and times in pg 9.3.5' do
|
193
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
194
|
+
io: fileio('dates_pg935.dat'),
|
195
|
+
column_types: { 0 => :date, 2 => :time }
|
196
|
+
)
|
197
|
+
r = decoder.read_line
|
198
|
+
expect(r.map { |f| f.is_a?(Time) ? f.to_f : f }).to eq [Date.parse('2015-04-08'), nil, Time.parse('2015-02-13 16:13:57.732772 UTC')].map { |f| f.is_a?(Time) ? f.to_f : f }
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'encodes big timestamp data correctly' do
|
202
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
203
|
+
io: fileio('timestamp_9.3.dat'),
|
204
|
+
column_types: { 0 => :time }
|
205
|
+
)
|
206
|
+
r = decoder.read_line
|
207
|
+
expect(r.map { |f| f.is_a?(Time) ? f.to_f : f }).to eq [Time.parse('2014-12-02 16:01:22.437311 UTC')].map { |f| f.is_a?(Time) ? f.to_f : f }
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'encodes float data correctly' do
|
211
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
212
|
+
io: fileio('float.dat'),
|
213
|
+
column_types: { 0 => :float }
|
214
|
+
)
|
215
|
+
r = decoder.read_line
|
216
|
+
expect(r).to eq [1_234_567.1234567]
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'encodes uuid correctly from tempfile' do
|
220
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
221
|
+
io: fileio('uuid.dat'),
|
222
|
+
column_types: { 0 => :uuid }
|
223
|
+
)
|
224
|
+
r = decoder.read_line
|
225
|
+
expect(r).to eq ['e876eef5-a116-4a27-b71f-bac4a1dcd20e']
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'encodes null uuid correctly from tempfile' do
|
229
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
230
|
+
io: fileio('empty_uuid.dat'),
|
231
|
+
column_types: { 0 => :string, 1 => :uuid, 2 => :uuid, 3 => :integer }
|
232
|
+
)
|
233
|
+
r = decoder.read_line
|
234
|
+
expect(r).to eq ['before2', nil, nil, 123_423_423]
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'encodes uuid correctly from tempfile' do
|
238
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
239
|
+
io: fileio('uuid_array.dat'),
|
240
|
+
column_types: { 0 => :array }
|
241
|
+
)
|
242
|
+
r = decoder.read_line
|
243
|
+
expect(r).to eq [['6272bd7d-adae-44b7-bba1-dca871c2a6fd', '7dc8431f-fcce-4d4d-86f3-6857cba47d38']]
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'encodes utf8 string correctly' do
|
247
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
248
|
+
io: fileio('utf8.dat'),
|
249
|
+
column_types: { 0 => :string }
|
250
|
+
)
|
251
|
+
r = decoder.read_line
|
252
|
+
expect(r).to eq ['Ekström']
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'encodes bigint as int correctly from tempfile' do
|
256
|
+
decoder = ActiveRecordCopy::Decoder.new(
|
257
|
+
io: fileio('bigint.dat'),
|
258
|
+
column_types: { 0 => :bigint, 1 => :string }
|
259
|
+
)
|
260
|
+
r = decoder.read_line
|
261
|
+
expect(r).to eq [23_372_036_854_775_808, 'test']
|
262
|
+
end
|
263
|
+
end
|