1 package pgtype_test
2
3 import (
4 "reflect"
5 "testing"
6 "time"
7
8 "github.com/jackc/pgtype"
9 "github.com/jackc/pgtype/testutil"
10 )
11
12 func TestTimestamptzArrayTranscode(t *testing.T) {
13 testutil.TestSuccessfulTranscodeEqFunc(t, "timestamptz[]", []interface{}{
14 &pgtype.TimestamptzArray{
15 Elements: nil,
16 Dimensions: nil,
17 Status: pgtype.Present,
18 },
19 &pgtype.TimestamptzArray{
20 Elements: []pgtype.Timestamptz{
21 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
22 {Status: pgtype.Null},
23 },
24 Dimensions: []pgtype.ArrayDimension{{Length: 2, LowerBound: 1}},
25 Status: pgtype.Present,
26 },
27 &pgtype.TimestamptzArray{Status: pgtype.Null},
28 &pgtype.TimestamptzArray{
29 Elements: []pgtype.Timestamptz{
30 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
31 {Time: time.Date(2016, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
32 {Time: time.Date(2017, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
33 {Time: time.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
34 {Status: pgtype.Null},
35 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
36 },
37 Dimensions: []pgtype.ArrayDimension{{Length: 3, LowerBound: 1}, {Length: 2, LowerBound: 1}},
38 Status: pgtype.Present,
39 },
40 &pgtype.TimestamptzArray{
41 Elements: []pgtype.Timestamptz{
42 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
43 {Time: time.Date(2015, 2, 2, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
44 {Time: time.Date(2015, 2, 3, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
45 {Time: time.Date(2015, 2, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
46 },
47 Dimensions: []pgtype.ArrayDimension{
48 {Length: 2, LowerBound: 4},
49 {Length: 2, LowerBound: 2},
50 },
51 Status: pgtype.Present,
52 },
53 }, func(a, b interface{}) bool {
54 ata := a.(pgtype.TimestamptzArray)
55 bta := b.(pgtype.TimestamptzArray)
56
57 if len(ata.Elements) != len(bta.Elements) || ata.Status != bta.Status {
58 return false
59 }
60
61 for i := range ata.Elements {
62 ae, be := ata.Elements[i], bta.Elements[i]
63 if !(ae.Time.Equal(be.Time) && ae.Status == be.Status && ae.InfinityModifier == be.InfinityModifier) {
64 return false
65 }
66 }
67
68 return true
69 })
70 }
71
72 func TestTimestamptzArraySet(t *testing.T) {
73 successfulTests := []struct {
74 source interface{}
75 result pgtype.TimestamptzArray
76 }{
77 {
78 source: []time.Time{time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC)},
79 result: pgtype.TimestamptzArray{
80 Elements: []pgtype.Timestamptz{{Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
81 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
82 Status: pgtype.Present},
83 },
84 {
85 source: (([]time.Time)(nil)),
86 result: pgtype.TimestamptzArray{Status: pgtype.Null},
87 },
88 {
89 source: [][]time.Time{
90 {time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC)},
91 {time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC)}},
92 result: pgtype.TimestamptzArray{
93 Elements: []pgtype.Timestamptz{
94 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
95 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
96 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
97 Status: pgtype.Present},
98 },
99 {
100 source: [][][][]time.Time{
101 {{{
102 time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC),
103 time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC),
104 time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC)}}},
105 {{{
106 time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC),
107 time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC),
108 time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC)}}}},
109 result: pgtype.TimestamptzArray{
110 Elements: []pgtype.Timestamptz{
111 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
112 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
113 {Time: time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
114 {Time: time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
115 {Time: time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
116 {Time: time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
117 Dimensions: []pgtype.ArrayDimension{
118 {LowerBound: 1, Length: 2},
119 {LowerBound: 1, Length: 1},
120 {LowerBound: 1, Length: 1},
121 {LowerBound: 1, Length: 3}},
122 Status: pgtype.Present},
123 },
124 {
125 source: [2][1]time.Time{
126 {time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC)},
127 {time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC)}},
128 result: pgtype.TimestamptzArray{
129 Elements: []pgtype.Timestamptz{
130 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
131 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
132 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
133 Status: pgtype.Present},
134 },
135 {
136 source: [2][1][1][3]time.Time{
137 {{{
138 time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC),
139 time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC),
140 time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC)}}},
141 {{{
142 time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC),
143 time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC),
144 time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC)}}}},
145 result: pgtype.TimestamptzArray{
146 Elements: []pgtype.Timestamptz{
147 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
148 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
149 {Time: time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
150 {Time: time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
151 {Time: time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
152 {Time: time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
153 Dimensions: []pgtype.ArrayDimension{
154 {LowerBound: 1, Length: 2},
155 {LowerBound: 1, Length: 1},
156 {LowerBound: 1, Length: 1},
157 {LowerBound: 1, Length: 3}},
158 Status: pgtype.Present},
159 },
160 }
161
162 for i, tt := range successfulTests {
163 var r pgtype.TimestamptzArray
164 err := r.Set(tt.source)
165 if err != nil {
166 t.Errorf("%d: %v", i, err)
167 }
168
169 if !reflect.DeepEqual(r, tt.result) {
170 t.Errorf("%d: expected %v to convert to %v, but it was %v", i, tt.source, tt.result, r)
171 }
172 }
173 }
174
175 func TestTimestamptzArrayAssignTo(t *testing.T) {
176 var timeSlice []time.Time
177 var timeSliceDim2 [][]time.Time
178 var timeSliceDim4 [][][][]time.Time
179 var timeArrayDim2 [2][1]time.Time
180 var timeArrayDim4 [2][1][1][3]time.Time
181
182 simpleTests := []struct {
183 src pgtype.TimestamptzArray
184 dst interface{}
185 expected interface{}
186 }{
187 {
188 src: pgtype.TimestamptzArray{
189 Elements: []pgtype.Timestamptz{{Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
190 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
191 Status: pgtype.Present,
192 },
193 dst: &timeSlice,
194 expected: []time.Time{time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC)},
195 },
196 {
197 src: pgtype.TimestamptzArray{Status: pgtype.Null},
198 dst: &timeSlice,
199 expected: (([]time.Time)(nil)),
200 },
201 {
202 src: pgtype.TimestamptzArray{Status: pgtype.Present},
203 dst: &timeSlice,
204 expected: []time.Time{},
205 },
206 {
207 src: pgtype.TimestamptzArray{
208 Elements: []pgtype.Timestamptz{
209 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
210 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
211 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
212 Status: pgtype.Present},
213 dst: &timeSliceDim2,
214 expected: [][]time.Time{
215 {time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC)},
216 {time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC)}},
217 },
218 {
219 src: pgtype.TimestamptzArray{
220 Elements: []pgtype.Timestamptz{
221 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
222 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
223 {Time: time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
224 {Time: time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
225 {Time: time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
226 {Time: time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
227 Dimensions: []pgtype.ArrayDimension{
228 {LowerBound: 1, Length: 2},
229 {LowerBound: 1, Length: 1},
230 {LowerBound: 1, Length: 1},
231 {LowerBound: 1, Length: 3}},
232 Status: pgtype.Present},
233 dst: &timeSliceDim4,
234 expected: [][][][]time.Time{
235 {{{
236 time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC),
237 time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC),
238 time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC)}}},
239 {{{
240 time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC),
241 time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC),
242 time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC)}}}},
243 },
244 {
245 src: pgtype.TimestamptzArray{
246 Elements: []pgtype.Timestamptz{
247 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
248 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
249 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
250 Status: pgtype.Present},
251 dst: &timeArrayDim2,
252 expected: [2][1]time.Time{
253 {time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC)},
254 {time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC)}},
255 },
256 {
257 src: pgtype.TimestamptzArray{
258 Elements: []pgtype.Timestamptz{
259 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
260 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
261 {Time: time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
262 {Time: time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
263 {Time: time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
264 {Time: time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
265 Dimensions: []pgtype.ArrayDimension{
266 {LowerBound: 1, Length: 2},
267 {LowerBound: 1, Length: 1},
268 {LowerBound: 1, Length: 1},
269 {LowerBound: 1, Length: 3}},
270 Status: pgtype.Present},
271 dst: &timeArrayDim4,
272 expected: [2][1][1][3]time.Time{
273 {{{
274 time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC),
275 time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC),
276 time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC)}}},
277 {{{
278 time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC),
279 time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC),
280 time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC)}}}},
281 },
282 }
283
284 for i, tt := range simpleTests {
285 err := tt.src.AssignTo(tt.dst)
286 if err != nil {
287 t.Errorf("%d: %v", i, err)
288 }
289
290 if dst := reflect.ValueOf(tt.dst).Elem().Interface(); !reflect.DeepEqual(dst, tt.expected) {
291 t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
292 }
293 }
294
295 errorTests := []struct {
296 src pgtype.TimestamptzArray
297 dst interface{}
298 }{
299 {
300 src: pgtype.TimestamptzArray{
301 Elements: []pgtype.Timestamptz{{Status: pgtype.Null}},
302 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
303 Status: pgtype.Present,
304 },
305 dst: &timeSlice,
306 },
307 {
308 src: pgtype.TimestamptzArray{
309 Elements: []pgtype.Timestamptz{
310 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
311 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
312 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}, {LowerBound: 1, Length: 2}},
313 Status: pgtype.Present},
314 dst: &timeArrayDim2,
315 },
316 {
317 src: pgtype.TimestamptzArray{
318 Elements: []pgtype.Timestamptz{
319 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
320 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
321 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}, {LowerBound: 1, Length: 2}},
322 Status: pgtype.Present},
323 dst: &timeSlice,
324 },
325 {
326 src: pgtype.TimestamptzArray{
327 Elements: []pgtype.Timestamptz{
328 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
329 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
330 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
331 Status: pgtype.Present},
332 dst: &timeArrayDim4,
333 },
334 }
335
336 for i, tt := range errorTests {
337 err := tt.src.AssignTo(tt.dst)
338 if err == nil {
339 t.Errorf("%d: expected error but none was returned (%v -> %v)", i, tt.src, tt.dst)
340 }
341 }
342
343 }
344
View as plain text