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 TestTimestampArrayTranscode(t *testing.T) {
13 testutil.TestSuccessfulTranscodeEqFunc(t, "timestamp[]", []interface{}{
14 &pgtype.TimestampArray{
15 Elements: nil,
16 Dimensions: nil,
17 Status: pgtype.Present,
18 },
19 &pgtype.TimestampArray{
20 Elements: []pgtype.Timestamp{
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.TimestampArray{Status: pgtype.Null},
28 &pgtype.TimestampArray{
29 Elements: []pgtype.Timestamp{
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.TimestampArray{
41 Elements: []pgtype.Timestamp{
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.TimestampArray)
55 bta := b.(pgtype.TimestampArray)
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 TestTimestampArraySet(t *testing.T) {
73 successfulTests := []struct {
74 source interface{}
75 result pgtype.TimestampArray
76 }{
77 {
78 source: []time.Time{time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC)},
79 result: pgtype.TimestampArray{
80 Elements: []pgtype.Timestamp{{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.TimestampArray{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.TimestampArray{
93 Elements: []pgtype.Timestamp{
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.TimestampArray{
110 Elements: []pgtype.Timestamp{
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
126 for i, tt := range successfulTests {
127 var r pgtype.TimestampArray
128 err := r.Set(tt.source)
129 if err != nil {
130 t.Errorf("%d: %v", i, err)
131 }
132
133 if !reflect.DeepEqual(r, tt.result) {
134 t.Errorf("%d: expected %v to convert to %v, but it was %v", i, tt.source, tt.result, r)
135 }
136 }
137 }
138
139 func TestTimestampArrayAssignTo(t *testing.T) {
140 var timeSlice []time.Time
141 var timeSliceDim2 [][]time.Time
142 var timeSliceDim4 [][][][]time.Time
143 var timeArrayDim2 [2][1]time.Time
144 var timeArrayDim4 [2][1][1][3]time.Time
145
146 simpleTests := []struct {
147 src pgtype.TimestampArray
148 dst interface{}
149 expected interface{}
150 }{
151 {
152 src: pgtype.TimestampArray{
153 Elements: []pgtype.Timestamp{{Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
154 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
155 Status: pgtype.Present,
156 },
157 dst: &timeSlice,
158 expected: []time.Time{time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC)},
159 },
160 {
161 src: pgtype.TimestampArray{Status: pgtype.Null},
162 dst: &timeSlice,
163 expected: (([]time.Time)(nil)),
164 },
165 {
166 src: pgtype.TimestampArray{Status: pgtype.Present},
167 dst: &timeSlice,
168 expected: []time.Time{},
169 },
170 {
171 src: pgtype.TimestampArray{
172 Elements: []pgtype.Timestamp{
173 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
174 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
175 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
176 Status: pgtype.Present},
177 dst: &timeSliceDim2,
178 expected: [][]time.Time{
179 {time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC)},
180 {time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC)}},
181 },
182 {
183 src: pgtype.TimestampArray{
184 Elements: []pgtype.Timestamp{
185 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
186 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
187 {Time: time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
188 {Time: time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
189 {Time: time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
190 {Time: time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
191 Dimensions: []pgtype.ArrayDimension{
192 {LowerBound: 1, Length: 2},
193 {LowerBound: 1, Length: 1},
194 {LowerBound: 1, Length: 1},
195 {LowerBound: 1, Length: 3}},
196 Status: pgtype.Present},
197 dst: &timeSliceDim4,
198 expected: [][][][]time.Time{
199 {{{
200 time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC),
201 time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC),
202 time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC)}}},
203 {{{
204 time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC),
205 time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC),
206 time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC)}}}},
207 },
208 {
209 src: pgtype.TimestampArray{
210 Elements: []pgtype.Timestamp{
211 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
212 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
213 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
214 Status: pgtype.Present},
215 dst: &timeArrayDim2,
216 expected: [2][1]time.Time{
217 {time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC)},
218 {time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC)}},
219 },
220 {
221 src: pgtype.TimestampArray{
222 Elements: []pgtype.Timestamp{
223 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
224 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
225 {Time: time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
226 {Time: time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
227 {Time: time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
228 {Time: time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
229 Dimensions: []pgtype.ArrayDimension{
230 {LowerBound: 1, Length: 2},
231 {LowerBound: 1, Length: 1},
232 {LowerBound: 1, Length: 1},
233 {LowerBound: 1, Length: 3}},
234 Status: pgtype.Present},
235 dst: &timeArrayDim4,
236 expected: [2][1][1][3]time.Time{
237 {{{
238 time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC),
239 time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC),
240 time.Date(2017, 5, 6, 0, 0, 0, 0, time.UTC)}}},
241 {{{
242 time.Date(2018, 7, 8, 0, 0, 0, 0, time.UTC),
243 time.Date(2019, 9, 10, 0, 0, 0, 0, time.UTC),
244 time.Date(2020, 11, 12, 0, 0, 0, 0, time.UTC)}}}},
245 },
246 }
247
248 for i, tt := range simpleTests {
249 err := tt.src.AssignTo(tt.dst)
250 if err != nil {
251 t.Errorf("%d: %v", i, err)
252 }
253
254 if dst := reflect.ValueOf(tt.dst).Elem().Interface(); !reflect.DeepEqual(dst, tt.expected) {
255 t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
256 }
257 }
258
259 errorTests := []struct {
260 src pgtype.TimestampArray
261 dst interface{}
262 }{
263 {
264 src: pgtype.TimestampArray{
265 Elements: []pgtype.Timestamp{{Status: pgtype.Null}},
266 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
267 Status: pgtype.Present,
268 },
269 dst: &timeSlice,
270 },
271 {
272 src: pgtype.TimestampArray{
273 Elements: []pgtype.Timestamp{
274 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
275 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
276 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}, {LowerBound: 1, Length: 2}},
277 Status: pgtype.Present},
278 dst: &timeArrayDim2,
279 },
280 {
281 src: pgtype.TimestampArray{
282 Elements: []pgtype.Timestamp{
283 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
284 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
285 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}, {LowerBound: 1, Length: 2}},
286 Status: pgtype.Present},
287 dst: &timeSlice,
288 },
289 {
290 src: pgtype.TimestampArray{
291 Elements: []pgtype.Timestamp{
292 {Time: time.Date(2015, 2, 1, 0, 0, 0, 0, time.UTC), Status: pgtype.Present},
293 {Time: time.Date(2016, 3, 4, 0, 0, 0, 0, time.UTC), Status: pgtype.Present}},
294 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
295 Status: pgtype.Present},
296 dst: &timeArrayDim4,
297 },
298 }
299
300 for i, tt := range errorTests {
301 err := tt.src.AssignTo(tt.dst)
302 if err == nil {
303 t.Errorf("%d: expected error but none was returned (%v -> %v)", i, tt.src, tt.dst)
304 }
305 }
306
307 }
308
View as plain text