torque-postgresql 1.1.8 → 2.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 +4 -4
- data/lib/torque/postgresql.rb +0 -2
- data/lib/torque/postgresql/adapter.rb +0 -1
- data/lib/torque/postgresql/adapter/database_statements.rb +4 -15
- data/lib/torque/postgresql/adapter/schema_creation.rb +13 -23
- data/lib/torque/postgresql/adapter/schema_definitions.rb +7 -21
- data/lib/torque/postgresql/adapter/schema_dumper.rb +71 -11
- data/lib/torque/postgresql/adapter/schema_statements.rb +2 -12
- data/lib/torque/postgresql/associations.rb +0 -3
- data/lib/torque/postgresql/associations/association.rb +0 -4
- data/lib/torque/postgresql/associations/association_scope.rb +18 -60
- data/lib/torque/postgresql/associations/belongs_to_many_association.rb +12 -15
- data/lib/torque/postgresql/associations/preloader.rb +0 -32
- data/lib/torque/postgresql/associations/preloader/association.rb +13 -10
- data/lib/torque/postgresql/autosave_association.rb +4 -4
- data/lib/torque/postgresql/auxiliary_statement.rb +1 -13
- data/lib/torque/postgresql/coder.rb +1 -2
- data/lib/torque/postgresql/config.rb +0 -6
- data/lib/torque/postgresql/inheritance.rb +13 -17
- data/lib/torque/postgresql/reflection/abstract_reflection.rb +19 -25
- data/lib/torque/postgresql/reflection/belongs_to_many_reflection.rb +4 -38
- data/lib/torque/postgresql/relation.rb +11 -16
- data/lib/torque/postgresql/relation/auxiliary_statement.rb +2 -8
- data/lib/torque/postgresql/relation/distinct_on.rb +1 -1
- data/lib/torque/postgresql/version.rb +1 -1
- data/spec/en.yml +19 -0
- data/spec/factories/authors.rb +6 -0
- data/spec/factories/comments.rb +13 -0
- data/spec/factories/posts.rb +6 -0
- data/spec/factories/tags.rb +5 -0
- data/spec/factories/texts.rb +5 -0
- data/spec/factories/users.rb +6 -0
- data/spec/factories/videos.rb +5 -0
- data/spec/mocks/cache_query.rb +16 -0
- data/spec/mocks/create_table.rb +35 -0
- data/spec/models/activity.rb +3 -0
- data/spec/models/activity_book.rb +4 -0
- data/spec/models/activity_post.rb +7 -0
- data/spec/models/activity_post/sample.rb +4 -0
- data/spec/models/author.rb +4 -0
- data/spec/models/author_journalist.rb +4 -0
- data/spec/models/comment.rb +3 -0
- data/spec/models/course.rb +2 -0
- data/spec/models/geometry.rb +2 -0
- data/spec/models/guest_comment.rb +4 -0
- data/spec/models/post.rb +6 -0
- data/spec/models/tag.rb +2 -0
- data/spec/models/text.rb +2 -0
- data/spec/models/time_keeper.rb +2 -0
- data/spec/models/user.rb +8 -0
- data/spec/models/video.rb +2 -0
- data/spec/schema.rb +141 -0
- data/spec/spec_helper.rb +59 -0
- data/spec/tests/arel_spec.rb +72 -0
- data/spec/tests/auxiliary_statement_spec.rb +593 -0
- data/spec/tests/belongs_to_many_spec.rb +240 -0
- data/spec/tests/coder_spec.rb +367 -0
- data/spec/tests/collector_spec.rb +59 -0
- data/spec/tests/distinct_on_spec.rb +65 -0
- data/spec/tests/enum_set_spec.rb +306 -0
- data/spec/tests/enum_spec.rb +621 -0
- data/spec/tests/geometric_builder_spec.rb +221 -0
- data/spec/tests/has_many_spec.rb +390 -0
- data/spec/tests/interval_spec.rb +167 -0
- data/spec/tests/lazy_spec.rb +24 -0
- data/spec/tests/period_spec.rb +954 -0
- data/spec/tests/quoting_spec.rb +24 -0
- data/spec/tests/range_spec.rb +36 -0
- data/spec/tests/relation_spec.rb +57 -0
- data/spec/tests/table_inheritance_spec.rb +403 -0
- metadata +103 -15
- data/lib/torque/postgresql/associations/join_dependency/join_association.rb +0 -15
- data/lib/torque/postgresql/schema_dumper.rb +0 -101
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'BelongsToMany' do
|
4
|
+
context 'on model' do
|
5
|
+
let(:model) { Video }
|
6
|
+
let(:builder) { Torque::PostgreSQL::Associations::Builder::BelongsToMany }
|
7
|
+
let(:reflection) { Torque::PostgreSQL::Reflection::BelongsToManyReflection }
|
8
|
+
after { model._reflections = {} }
|
9
|
+
|
10
|
+
it 'has the builder method' do
|
11
|
+
expect(model).to respond_to(:belongs_to_many)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'triggers the correct builder and relation' do
|
15
|
+
expect(builder).to receive(:build).with(anything, :tests, nil, {}) do |_, name, _, _|
|
16
|
+
ActiveRecord::Reflection.create(:belongs_to_many, name, nil, {}, model)
|
17
|
+
end
|
18
|
+
|
19
|
+
expect(reflection).to receive(:new).with(:tests, nil, {}, model)
|
20
|
+
|
21
|
+
model.belongs_to_many(:tests)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'on association' do
|
26
|
+
let(:other) { Tag }
|
27
|
+
let(:initial) { FactoryBot.create(:tag) }
|
28
|
+
|
29
|
+
before { Video.belongs_to_many :tags }
|
30
|
+
subject { Video.create(title: 'A') }
|
31
|
+
after { Video._reflections = {} }
|
32
|
+
|
33
|
+
it 'has the method' do
|
34
|
+
expect(subject).to respond_to(:tags)
|
35
|
+
expect(subject._reflections).to include('tags')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'loads associated records' do
|
39
|
+
subject.update(tag_ids: [initial.id])
|
40
|
+
expect(subject.tags.to_sql).to be_eql(<<-SQL.squish)
|
41
|
+
SELECT "tags".* FROM "tags" WHERE "tags"."id" IN (#{initial.id})
|
42
|
+
SQL
|
43
|
+
|
44
|
+
expect(subject.tags.load).to be_a(ActiveRecord::Associations::CollectionProxy)
|
45
|
+
expect(subject.tags.to_a).to be_eql([initial])
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'can be marked as loaded' do
|
49
|
+
expect(subject.tags.loaded?).to be_eql(false)
|
50
|
+
expect(subject.tags).to respond_to(:load_target)
|
51
|
+
expect(subject.tags.load_target).to be_eql([])
|
52
|
+
expect(subject.tags.loaded?).to be_eql(true)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'can find specific records' do
|
56
|
+
records = FactoryBot.create_list(:tag, 10)
|
57
|
+
subject.update(tag_ids: records.map(&:id))
|
58
|
+
ids = records.map(&:id).sample(5)
|
59
|
+
|
60
|
+
expect(subject.tags).to respond_to(:find)
|
61
|
+
records = subject.tags.find(*ids)
|
62
|
+
|
63
|
+
expect(records.size).to be_eql(5)
|
64
|
+
expect(records.map(&:id).sort).to be_eql(ids.sort)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'can return last n records' do
|
68
|
+
records = FactoryBot.create_list(:tag, 10)
|
69
|
+
subject.update(tag_ids: records.map(&:id))
|
70
|
+
ids = records.map(&:id).last(5)
|
71
|
+
|
72
|
+
expect(subject.tags).to respond_to(:last)
|
73
|
+
records = subject.tags.last(5)
|
74
|
+
|
75
|
+
expect(records.size).to be_eql(5)
|
76
|
+
expect(records.map(&:id).sort).to be_eql(ids.sort)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'can return first n records' do
|
80
|
+
records = FactoryBot.create_list(:tag, 10)
|
81
|
+
subject.update(tag_ids: records.map(&:id))
|
82
|
+
ids = records.map(&:id).first(5)
|
83
|
+
|
84
|
+
expect(subject.tags).to respond_to(:take)
|
85
|
+
records = subject.tags.take(5)
|
86
|
+
|
87
|
+
expect(records.size).to be_eql(5)
|
88
|
+
expect(records.map(&:id).sort).to be_eql(ids.sort)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'can build an associated record' do
|
92
|
+
record = subject.tags.build(name: 'Test')
|
93
|
+
expect(record).to be_a(other)
|
94
|
+
expect(record).not_to be_persisted
|
95
|
+
expect(record.name).to be_eql('Test')
|
96
|
+
|
97
|
+
expect(subject.save).to be_truthy
|
98
|
+
expect(subject.tag_ids).to be_eql([record.id])
|
99
|
+
expect(subject.tags.size).to be_eql(1)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'can create an associated record' do
|
103
|
+
record = subject.tags.create(name: 'Test')
|
104
|
+
expect(subject.tags).to respond_to(:create!)
|
105
|
+
|
106
|
+
expect(record).to be_a(other)
|
107
|
+
expect(record).to be_persisted
|
108
|
+
expect(record.name).to be_eql('Test')
|
109
|
+
expect(subject.tag_ids).to be_eql([record.id])
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'can concat records' do
|
113
|
+
record = FactoryBot.create(:tag)
|
114
|
+
subject.update(tag_ids: [record.id])
|
115
|
+
expect(subject.tags.size).to be_eql(1)
|
116
|
+
|
117
|
+
subject.tags.concat(other.new(name: 'Test'))
|
118
|
+
subject.tags.reload
|
119
|
+
expect(subject.tags.size).to be_eql(2)
|
120
|
+
expect(subject.tag_ids.size).to be_eql(2)
|
121
|
+
expect(subject.tags.last.name).to be_eql('Test')
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'can replace records' do
|
125
|
+
subject.tags << FactoryBot.create(:tag)
|
126
|
+
expect(subject.tags.size).to be_eql(1)
|
127
|
+
|
128
|
+
subject.tags.replace([other.new(name: 'Test 1'), other.new(name: 'Test 2')])
|
129
|
+
expect(subject.tags.size).to be_eql(2)
|
130
|
+
expect(subject.tags[0].name).to be_eql('Test 1')
|
131
|
+
expect(subject.tags[1].name).to be_eql('Test 2')
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'can delete all records' do
|
135
|
+
subject.tags.concat(FactoryBot.create_list(:tag, 5))
|
136
|
+
expect(subject.tags.size).to be_eql(5)
|
137
|
+
|
138
|
+
subject.tags.delete_all
|
139
|
+
expect(subject.tags.size).to be_eql(0)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'can destroy all records' do
|
143
|
+
subject.tags.concat(FactoryBot.create_list(:tag, 5))
|
144
|
+
expect(subject.tags.size).to be_eql(5)
|
145
|
+
|
146
|
+
subject.tags.destroy_all
|
147
|
+
expect(subject.tags.size).to be_eql(0)
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'can have sum operations' do
|
151
|
+
records = FactoryBot.create_list(:tag, 5)
|
152
|
+
subject.tags.concat(records)
|
153
|
+
|
154
|
+
result = records.map(&:id).reduce(:+)
|
155
|
+
expect(subject.tags).to respond_to(:sum)
|
156
|
+
expect(subject.tags.sum(:id)).to be_eql(result)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'can have a pluck operation' do
|
160
|
+
records = FactoryBot.create_list(:tag, 5)
|
161
|
+
subject.tags.concat(records)
|
162
|
+
|
163
|
+
result = records.map(&:name).sort
|
164
|
+
expect(subject.tags).to respond_to(:pluck)
|
165
|
+
expect(subject.tags.pluck(:name).sort).to be_eql(result)
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'can be markes as empty' do
|
169
|
+
expect(subject.tags).to respond_to(:empty?)
|
170
|
+
expect(subject.tags.empty?).to be_truthy
|
171
|
+
|
172
|
+
subject.tags << FactoryBot.create(:tag)
|
173
|
+
expect(subject.tags.empty?).to be_falsey
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'can check if a record is included on the list' do
|
177
|
+
outside = FactoryBot.create(:tag)
|
178
|
+
inside = FactoryBot.create(:tag)
|
179
|
+
subject.tags << inside
|
180
|
+
|
181
|
+
expect(subject.tags).to respond_to(:include?)
|
182
|
+
expect(subject.tags.include?(inside)).to be_truthy
|
183
|
+
expect(subject.tags.include?(outside)).to be_falsey
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'can append records' do
|
187
|
+
subject.tags << other.new(name: 'Test 1')
|
188
|
+
expect(subject.tags.size).to be_eql(1)
|
189
|
+
|
190
|
+
subject.tags << other.new(name: 'Test 2')
|
191
|
+
expect(subject.tags.size).to be_eql(2)
|
192
|
+
expect(subject.tags.last.name).to be_eql('Test 2')
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'can clear records' do
|
196
|
+
subject.tags << FactoryBot.create(:tag)
|
197
|
+
expect(subject.tags.size).to be_eql(1)
|
198
|
+
|
199
|
+
subject.tags.clear
|
200
|
+
expect(subject.tags.size).to be_eql(0)
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'can reload records' do
|
204
|
+
expect(subject.tags.size).to be_eql(0)
|
205
|
+
subject.tags << FactoryBot.create(:tag)
|
206
|
+
|
207
|
+
subject.tags.reload
|
208
|
+
expect(subject.tags.size).to be_eql(1)
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'can preload records' do
|
212
|
+
records = FactoryBot.create_list(:tag, 5)
|
213
|
+
subject.tags.concat(records)
|
214
|
+
|
215
|
+
entries = Video.all.includes(:tags).load
|
216
|
+
|
217
|
+
expect(entries.size).to be_eql(1)
|
218
|
+
expect(entries.first.tags).to be_loaded
|
219
|
+
expect(entries.first.tags.size).to be_eql(5)
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'can joins records' do
|
223
|
+
query = Video.all.joins(:tags)
|
224
|
+
expect(query.to_sql).to match(/INNER JOIN "tags"/)
|
225
|
+
expect { query.load }.not_to raise_error
|
226
|
+
end
|
227
|
+
|
228
|
+
context "When record is not persisted" do
|
229
|
+
let(:initial) { FactoryBot.create(:tag) }
|
230
|
+
before { Video.belongs_to_many :tags }
|
231
|
+
subject { Video.new(title: 'A', tags: [initial]) }
|
232
|
+
after { Video._reflections = {} }
|
233
|
+
|
234
|
+
it 'loads associated records' do
|
235
|
+
expect(subject.tags.load).to be_a(ActiveRecord::Associations::CollectionProxy)
|
236
|
+
expect(subject.tags.to_a).to be_eql([initial])
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -0,0 +1,367 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'Complex coder', type: :helper do
|
4
|
+
let(:coder) { Torque::PostgreSQL::Coder }
|
5
|
+
|
6
|
+
context 'on decode' do
|
7
|
+
|
8
|
+
context 'one dimensional arrays' do
|
9
|
+
it 'returns an empty array' do
|
10
|
+
expect(coder.decode(%[{}])).to eql []
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns an array of strings' do
|
14
|
+
expect(coder.decode(%[{1,2,3}])).to eql ['1','2','3']
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns an array of strings, with nils replacing NULL characters' do
|
18
|
+
expect(coder.decode(%[{1,,NULL}])).to eql ['1',nil,nil]
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns an array with the word NULL' do
|
22
|
+
expect(coder.decode(%[{1,"NULL",3}])).to eql ['1','NULL','3']
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns an array of strings when containing commas in a quoted string' do
|
26
|
+
expect(coder.decode(%[{1,"2,3",4}])).to eql ['1','2,3','4']
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns an array of strings when containing an escaped quote' do
|
30
|
+
expect(coder.decode(%[{1,"2\\",3",4}])).to eql ['1','2",3','4']
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'returns an array of strings when containing an escaped backslash' do
|
34
|
+
expect(coder.decode(%[{1,"2\\\\",3,4}])).to eql ['1','2\\','3','4']
|
35
|
+
expect(coder.decode(%[{1,"2\\\\\\",3",4}])).to eql ['1','2\\",3','4']
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns an array containing empty strings' do
|
39
|
+
expect(coder.decode(%[{1,"",3,""}])).to eql ['1', '', '3', '']
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns an array containing unicode strings' do
|
43
|
+
expect(coder.decode(%[{"Paragraph 399(b)(i) – “valid leave” – meaning"}])).to eq(['Paragraph 399(b)(i) – “valid leave” – meaning'])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'two dimensional arrays' do
|
48
|
+
it 'returns an empty array' do
|
49
|
+
expect(coder.decode(%[{{}}])).to eql [[]]
|
50
|
+
expect(coder.decode(%[{{},{}}])).to eql [[],[]]
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns an array of strings with a sub array' do
|
54
|
+
expect(coder.decode(%[{1,{2,3},4}])).to eql ['1',['2','3'],'4']
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns an array of strings with a sub array' do
|
58
|
+
expect(coder.decode(%[{1,{"2,3"},4}])).to eql ['1',['2,3'],'4']
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns an array of strings with a sub array and a quoted }' do
|
62
|
+
expect(coder.decode(%[{1,{"2,}3",,NULL},4}])).to eql ['1',['2,}3',nil,nil],'4']
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'returns an array of strings with a sub array and a quoted {' do
|
66
|
+
expect(coder.decode(%[{1,{"2,{3"},4}])).to eql ['1',['2,{3'],'4']
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'returns an array of strings with a sub array and a quoted { and escaped quote' do
|
70
|
+
expect(coder.decode(%[{1,{"2\\",{3"},4}])).to eql ['1',['2",{3'],'4']
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'returns an array of strings with a sub array with empty strings' do
|
74
|
+
expect(coder.decode(%[{1,{""},4,{""}}])).to eql ['1',[''],'4',['']]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'three dimensional arrays' do
|
79
|
+
it 'returns an empty array' do
|
80
|
+
expect(coder.decode(%[{{{}}}])).to eql [[[]]]
|
81
|
+
expect(coder.decode(%[{{{},{}},{{},{}}}])).to eql [[[],[]],[[],[]]]
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'returns an array of strings with sub arrays' do
|
85
|
+
expect(coder.decode(%[{1,{2,{3,4}},{NULL,,6},7}])).to eql ['1',['2',['3','4']],[nil,nil,'6'],'7']
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'record syntax' do
|
90
|
+
it 'returns an empty array' do
|
91
|
+
expect(coder.decode(%[()])).to eql []
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'returns an array of strings' do
|
95
|
+
expect(coder.decode(%[(1,2,3)])).to eql ['1','2','3']
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'returns an array of strings, with nils replacing NULL characters' do
|
99
|
+
expect(coder.decode(%[(1,,NULL)])).to eql ['1',nil,nil]
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns an array with the word NULL' do
|
103
|
+
expect(coder.decode(%[(1,"NULL",3)])).to eql ['1','NULL','3']
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'returns an array of strings when containing commas in a quoted string' do
|
107
|
+
expect(coder.decode(%[(1,"2,3",4)])).to eql ['1','2,3','4']
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'returns an array of strings when containing an escaped quote' do
|
111
|
+
expect(coder.decode(%[(1,"2\\",3",4)])).to eql ['1','2",3','4']
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'returns an array of strings when containing an escaped backslash' do
|
115
|
+
expect(coder.decode(%[(1,"2\\\\",3,4)])).to eql ['1','2\\','3','4']
|
116
|
+
expect(coder.decode(%[(1,"2\\\\\\",3",4)])).to eql ['1','2\\",3','4']
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'returns an array containing empty strings' do
|
120
|
+
expect(coder.decode(%[(1,"",3,"")])).to eql ['1', '', '3', '']
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'returns an array containing unicode strings' do
|
124
|
+
expect(coder.decode(%[("Paragraph 399(b)(i) – “valid leave” – meaning")])).to eq(['Paragraph 399(b)(i) – “valid leave” – meaning'])
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'array of records' do
|
129
|
+
it 'returns an empty array' do
|
130
|
+
expect(coder.decode(%[{()}])).to eql [[]]
|
131
|
+
expect(coder.decode(%[{(),()}])).to eql [[],[]]
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'returns an array of strings with a sub array' do
|
135
|
+
expect(coder.decode(%[{1,(2,3),4}])).to eql ['1',['2','3'],'4']
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'returns an array of strings with a sub array' do
|
139
|
+
expect(coder.decode(%[{1,("2,3"),4}])).to eql ['1',['2,3'],'4']
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'returns an array of strings with a sub array and a quoted }' do
|
143
|
+
expect(coder.decode(%[{1,("2,}3",,NULL),4}])).to eql ['1',['2,}3',nil,nil],'4']
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'returns an array of strings with a sub array and a quoted {' do
|
147
|
+
expect(coder.decode(%[{1,("2,{3"),4}])).to eql ['1',['2,{3'],'4']
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'returns an array of strings with a sub array and a quoted { and escaped quote' do
|
151
|
+
expect(coder.decode(%[{1,("2\\",{3"),4}])).to eql ['1',['2",{3'],'4']
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'returns an array of strings with a sub array with empty strings' do
|
155
|
+
expect(coder.decode(%[{1,(""),4,("")}])).to eql ['1',[''],'4',['']]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'mix of record and array' do
|
160
|
+
it 'returns an empty array' do
|
161
|
+
expect(coder.decode(%[({()})])).to eql [[[]]]
|
162
|
+
expect(coder.decode(%[{({},{}),{(),{}}}])).to eql [[[],[]],[[],[]]]
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'returns an array of strings with sub arrays' do
|
166
|
+
expect(coder.decode(%[{1,(2,{3,4}),(NULL,,6),7}])).to eql ['1',['2',['3','4']],[nil,nil,'6'],'7']
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'record complex sample' do
|
171
|
+
it 'may have double double quotes translate to single double quotes' do
|
172
|
+
expect(coder.decode(%[("Test with double "" quoutes")])).to eql ['Test with double " quoutes']
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'double double quotes may occur any number of times' do
|
176
|
+
expect(coder.decode(%[("Only one ""","Now "" two "".",""",""{""}","""""")])).to eql ['Only one "', 'Now " two ".', '","{"}', '""']
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'may have any kind of value' do
|
180
|
+
expect(coder.decode(%[(String,123456,false,true,"2016-01-01 12:00:00",{1,2,3})])).to eql ['String', '123456', 'false', 'true', '2016-01-01 12:00:00', ['1', '2', '3']]
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'on encode' do
|
187
|
+
let(:record) { Torque::PostgreSQL::Coder::Record }
|
188
|
+
|
189
|
+
context 'one dimensional arrays' do
|
190
|
+
it 'receives an empty array' do
|
191
|
+
expect(coder.encode([])).to eql %[{}]
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'receives an array of strings' do
|
195
|
+
expect(coder.encode(['1','2','3'])).to eql %[{1,2,3}]
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'receives an array of strings, with nils replacing NULL characters' do
|
199
|
+
expect(coder.encode(['1',nil,nil])).to eql %[{1,NULL,NULL}]
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'receives an array with the word NULL' do
|
203
|
+
expect(coder.encode(['1','NULL','3'])).to eql %[{1,"NULL",3}]
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'receives an array of strings when containing commas in a quoted string' do
|
207
|
+
expect(coder.encode(['1','2,3','4'])).to eql %[{1,"2,3",4}]
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'receives an array of strings when containing an escaped quote' do
|
211
|
+
expect(coder.encode(['1','2",3','4'])).to eql %[{1,"2\\",3",4}]
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'receives an array of strings when containing an escaped backslash' do
|
215
|
+
expect(coder.encode(['1','2\\','3','4'])).to eql %[{1,"2\\\\",3,4}]
|
216
|
+
expect(coder.encode(['1','2\\",3','4'])).to eql %[{1,"2\\\\\\",3",4}]
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'receives an array containing empty strings' do
|
220
|
+
expect(coder.encode(['1', '', '3', ''])).to eql %[{1,"",3,""}]
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'receives an array containing unicode strings' do
|
224
|
+
expect(coder.encode(['Paragraph 399(b)(i) – “valid leave” – meaning'])).to eql %[{"Paragraph 399(b)(i) – “valid leave” – meaning"}]
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
context 'two dimensional arrays' do
|
229
|
+
it 'receives an empty array' do
|
230
|
+
expect(coder.encode([[]])).to eql %[{{}}]
|
231
|
+
expect(coder.encode([[],[]])).to eql %[{{},{}}]
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'receives an array of strings with a sub array' do
|
235
|
+
expect(coder.encode(['1',['2','3'],'4'])).to eql %[{1,{2,3},4}]
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'receives an array of strings with a sub array' do
|
239
|
+
expect(coder.encode(['1',['2,3'],'4'])).to eql %[{1,{"2,3"},4}]
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'receives an array of strings with a sub array and a quoted }' do
|
243
|
+
expect(coder.encode(['1',['2,}3',nil,nil],'4'])).to eql %[{1,{"2,}3",NULL,NULL},4}]
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'receives an array of strings with a sub array and a quoted {' do
|
247
|
+
expect(coder.encode(['1',['2,{3'],'4'])).to eql %[{1,{"2,{3"},4}]
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'receives an array of strings with a sub array and a quoted { and escaped quote' do
|
251
|
+
expect(coder.encode(['1',['2",{3'],'4'])).to eql %[{1,{"2\\",{3"},4}]
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'receives an array of strings with a sub array with empty strings' do
|
255
|
+
expect(coder.encode(['1',[''],'4',['']])).to eql %[{1,{""},4,{""}}]
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context 'three dimensional arrays' do
|
260
|
+
it 'receives an empty array' do
|
261
|
+
expect(coder.encode([[[]]])).to eql %[{{{}}}]
|
262
|
+
expect(coder.encode([[[],[]],[[],[]]])).to eql %[{{{},{}},{{},{}}}]
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'receives an array of strings with sub arrays' do
|
266
|
+
expect(coder.encode(['1',['2',['3','4']],[nil,nil,'6'],'7'])).to eql %[{1,{2,{3,4}},{NULL,NULL,6},7}]
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
context 'record syntax' do
|
271
|
+
it 'receives an empty array' do
|
272
|
+
expect(coder.encode( record.new )).to eql %[()]
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'receives an array of strings' do
|
276
|
+
expect(coder.encode( record.new(['1','2','3']) )).to eql %[(1,2,3)]
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'receives an array of strings, with nils replacing NULL characters' do
|
280
|
+
expect(coder.encode( record.new(['1',nil,nil]) )).to eql %[(1,,)]
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'receives an array with the word NULL' do
|
284
|
+
expect(coder.encode( record.new(['1','NULL','3']) )).to eql %[(1,"NULL",3)]
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'receives an array of strings when containing commas in a quoted string' do
|
288
|
+
expect(coder.encode( record.new(['1','2,3','4']) )).to eql %[(1,"2,3",4)]
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'receives an array of strings when containing an escaped quote' do
|
292
|
+
expect(coder.encode( record.new(['1','2",3','4']) )).to eql %[(1,"2\\",3",4)]
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'receives an array of strings when containing an escaped backslash' do
|
296
|
+
expect(coder.encode( record.new(['1','2\\','3','4']) )).to eql %[(1,"2\\\\",3,4)]
|
297
|
+
expect(coder.encode( record.new(['1','2\\",3','4']) )).to eql %[(1,"2\\\\\\",3",4)]
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'receives an array containing empty strings' do
|
301
|
+
expect(coder.encode( record.new(['1', '', '3', '']) )).to eql %[(1,"",3,"")]
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'receives an array containing unicode strings' do
|
305
|
+
expect(coder.encode( record.new(['Paragraph 399(b)(i) – “valid leave” – meaning']) )).to eql %[("Paragraph 399(b)(i) – “valid leave” – meaning")]
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
context 'array of records' do
|
310
|
+
it 'receives an empty array' do
|
311
|
+
expect(coder.encode([record.new])).to eql %[{()}]
|
312
|
+
expect(coder.encode([record.new,record.new])).to eql %[{(),()}]
|
313
|
+
end
|
314
|
+
|
315
|
+
it 'receives an array of strings with a sub array' do
|
316
|
+
expect(coder.encode(['1',record.new(['2','3']),'4'])).to eql %[{1,(2,3),4}]
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'receives an array of strings with a sub array' do
|
320
|
+
expect(coder.encode(['1',record.new(['2,3']),'4'])).to eql %[{1,("2,3"),4}]
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'receives an array of strings with a sub array and a quoted }' do
|
324
|
+
expect(coder.encode(['1',record.new(['2,}3',nil,nil]),'4'])).to eql %[{1,("2,}3",,),4}]
|
325
|
+
end
|
326
|
+
|
327
|
+
it 'receives an array of strings with a sub array and a quoted {' do
|
328
|
+
expect(coder.encode(['1',record.new(['2,{3']),'4'])).to eql %[{1,("2,{3"),4}]
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'receives an array of strings with a sub array and a quoted { and escaped quote' do
|
332
|
+
expect(coder.encode(['1',record.new(['2",{3']),'4'])).to eql %[{1,("2\\",{3"),4}]
|
333
|
+
end
|
334
|
+
|
335
|
+
it 'receives an array of strings with a sub array with empty strings' do
|
336
|
+
expect(coder.encode(['1',record.new(['']),'4',record.new([''])])).to eql %[{1,(""),4,("")}]
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
context 'mix of record and array' do
|
341
|
+
it 'receives an empty array' do
|
342
|
+
expect(coder.encode( record.new([[record.new,nil]]) )).to eql %[({(),NULL})]
|
343
|
+
expect(coder.encode( [record.new([[], []]),[record.new,[]]] )).to eql %[{({},{}),{(),{}}}]
|
344
|
+
end
|
345
|
+
|
346
|
+
it 'receives an array of strings with sub arrays' do
|
347
|
+
expect(coder.encode(['1',record.new(['2',['3','4']]),record.new([nil,nil,'6']),'7'])).to eql %[{1,(2,{3,4}),(,,6),7}]
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
context 'record complex sample' do
|
352
|
+
it 'may have double double quotes translate to single double quotes' do
|
353
|
+
expect(coder.encode( record.new(['Test with double " quoutes']) )).to eql %[("Test with double \\" quoutes")]
|
354
|
+
end
|
355
|
+
|
356
|
+
it 'double double quotes may occur any number of times' do
|
357
|
+
expect(coder.encode( record.new(['Only one "', 'Now " two ".', '","{"}', '""']) )).to eql %[("Only one \\"","Now \\" two \\".","\\",\\"{\\"}","\\"\\"")]
|
358
|
+
end
|
359
|
+
|
360
|
+
it 'may have any kind of value' do
|
361
|
+
expect(coder.encode( record.new(['String', '123456', 'false', 'true', '2016-01-01 12:00:00', ['1', '2', '3']]) )).to eql %[(String,123456,false,true,"2016-01-01 12:00:00",{1,2,3})]
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
end
|
366
|
+
|
367
|
+
end
|