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