1 package pgtype_test
2
3 import (
4 "reflect"
5 "testing"
6
7 "github.com/jackc/pgtype"
8 "github.com/jackc/pgtype/testutil"
9 "github.com/stretchr/testify/assert"
10 "github.com/stretchr/testify/require"
11 )
12
13
14 func TestTextArrayDecodeTextNull(t *testing.T) {
15 textArray := &pgtype.TextArray{}
16 err := textArray.DecodeText(nil, []byte(`{abc,"NULL",NULL,def}`))
17 require.NoError(t, err)
18 require.Len(t, textArray.Elements, 4)
19 assert.Equal(t, pgtype.Present, textArray.Elements[1].Status)
20 assert.Equal(t, pgtype.Null, textArray.Elements[2].Status)
21 }
22
23 func TestTextArrayTranscode(t *testing.T) {
24 testutil.TestSuccessfulTranscode(t, "text[]", []interface{}{
25 &pgtype.TextArray{
26 Elements: nil,
27 Dimensions: nil,
28 Status: pgtype.Present,
29 },
30 &pgtype.TextArray{
31 Elements: []pgtype.Text{
32 {String: "foo", Status: pgtype.Present},
33 {Status: pgtype.Null},
34 },
35 Dimensions: []pgtype.ArrayDimension{{Length: 2, LowerBound: 1}},
36 Status: pgtype.Present,
37 },
38 &pgtype.TextArray{Status: pgtype.Null},
39 &pgtype.TextArray{
40 Elements: []pgtype.Text{
41 {String: "bar ", Status: pgtype.Present},
42 {String: "NuLL", Status: pgtype.Present},
43 {String: `wow"quz\`, Status: pgtype.Present},
44 {String: "", Status: pgtype.Present},
45 {Status: pgtype.Null},
46 {String: "null", Status: pgtype.Present},
47 },
48 Dimensions: []pgtype.ArrayDimension{{Length: 3, LowerBound: 1}, {Length: 2, LowerBound: 1}},
49 Status: pgtype.Present,
50 },
51 &pgtype.TextArray{
52 Elements: []pgtype.Text{
53 {String: "bar", Status: pgtype.Present},
54 {String: "baz", Status: pgtype.Present},
55 {String: "quz", Status: pgtype.Present},
56 {String: "foo", Status: pgtype.Present},
57 },
58 Dimensions: []pgtype.ArrayDimension{
59 {Length: 2, LowerBound: 4},
60 {Length: 2, LowerBound: 2},
61 },
62 Status: pgtype.Present,
63 },
64 })
65 }
66
67 func TestTextArraySet(t *testing.T) {
68 successfulTests := []struct {
69 source interface{}
70 result pgtype.TextArray
71 }{
72 {
73 source: []string{"foo"},
74 result: pgtype.TextArray{
75 Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}},
76 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
77 Status: pgtype.Present},
78 },
79 {
80 source: (([]string)(nil)),
81 result: pgtype.TextArray{Status: pgtype.Null},
82 },
83 {
84 source: [][]string{{"foo"}, {"bar"}},
85 result: pgtype.TextArray{
86 Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}, {String: "bar", Status: pgtype.Present}},
87 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
88 Status: pgtype.Present},
89 },
90 {
91 source: [][][][]string{{{{"foo", "bar", "baz"}}}, {{{"wibble", "wobble", "wubble"}}}},
92 result: pgtype.TextArray{
93 Elements: []pgtype.Text{
94 {String: "foo", Status: pgtype.Present},
95 {String: "bar", Status: pgtype.Present},
96 {String: "baz", Status: pgtype.Present},
97 {String: "wibble", Status: pgtype.Present},
98 {String: "wobble", Status: pgtype.Present},
99 {String: "wubble", Status: pgtype.Present}},
100 Dimensions: []pgtype.ArrayDimension{
101 {LowerBound: 1, Length: 2},
102 {LowerBound: 1, Length: 1},
103 {LowerBound: 1, Length: 1},
104 {LowerBound: 1, Length: 3}},
105 Status: pgtype.Present},
106 },
107 {
108 source: [2][1]string{{"foo"}, {"bar"}},
109 result: pgtype.TextArray{
110 Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}, {String: "bar", Status: pgtype.Present}},
111 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
112 Status: pgtype.Present},
113 },
114 {
115 source: [2][1][1][3]string{{{{"foo", "bar", "baz"}}}, {{{"wibble", "wobble", "wubble"}}}},
116 result: pgtype.TextArray{
117 Elements: []pgtype.Text{
118 {String: "foo", Status: pgtype.Present},
119 {String: "bar", Status: pgtype.Present},
120 {String: "baz", Status: pgtype.Present},
121 {String: "wibble", Status: pgtype.Present},
122 {String: "wobble", Status: pgtype.Present},
123 {String: "wubble", Status: pgtype.Present}},
124 Dimensions: []pgtype.ArrayDimension{
125 {LowerBound: 1, Length: 2},
126 {LowerBound: 1, Length: 1},
127 {LowerBound: 1, Length: 1},
128 {LowerBound: 1, Length: 3}},
129 Status: pgtype.Present},
130 },
131 }
132
133 for i, tt := range successfulTests {
134 var r pgtype.TextArray
135 err := r.Set(tt.source)
136 if err != nil {
137 t.Errorf("%d: %v", i, err)
138 }
139
140 if !reflect.DeepEqual(r, tt.result) {
141 t.Errorf("%d: expected %v to convert to %v, but it was %v", i, tt.source, tt.result, r)
142 }
143 }
144 }
145
146 func TestTextArrayAssignTo(t *testing.T) {
147 var stringSlice []string
148 type _stringSlice []string
149 var namedStringSlice _stringSlice
150 var stringSliceDim2 [][]string
151 var stringSliceDim4 [][][][]string
152 var stringArrayDim2 [2][1]string
153 var stringArrayDim4 [2][1][1][3]string
154
155 simpleTests := []struct {
156 src pgtype.TextArray
157 dst interface{}
158 expected interface{}
159 }{
160 {
161 src: pgtype.TextArray{
162 Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}},
163 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
164 Status: pgtype.Present,
165 },
166 dst: &stringSlice,
167 expected: []string{"foo"},
168 },
169 {
170 src: pgtype.TextArray{
171 Elements: []pgtype.Text{{String: "bar", Status: pgtype.Present}},
172 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
173 Status: pgtype.Present,
174 },
175 dst: &namedStringSlice,
176 expected: _stringSlice{"bar"},
177 },
178 {
179 src: pgtype.TextArray{Status: pgtype.Null},
180 dst: &stringSlice,
181 expected: (([]string)(nil)),
182 },
183 {
184 src: pgtype.TextArray{Status: pgtype.Present},
185 dst: &stringSlice,
186 expected: []string{},
187 },
188 {
189 src: pgtype.TextArray{
190 Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}, {String: "bar", Status: pgtype.Present}},
191 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
192 Status: pgtype.Present},
193 dst: &stringSliceDim2,
194 expected: [][]string{{"foo"}, {"bar"}},
195 },
196 {
197 src: pgtype.TextArray{
198 Elements: []pgtype.Text{
199 {String: "foo", Status: pgtype.Present},
200 {String: "bar", Status: pgtype.Present},
201 {String: "baz", Status: pgtype.Present},
202 {String: "wibble", Status: pgtype.Present},
203 {String: "wobble", Status: pgtype.Present},
204 {String: "wubble", Status: pgtype.Present}},
205 Dimensions: []pgtype.ArrayDimension{
206 {LowerBound: 1, Length: 2},
207 {LowerBound: 1, Length: 1},
208 {LowerBound: 1, Length: 1},
209 {LowerBound: 1, Length: 3}},
210 Status: pgtype.Present},
211 dst: &stringSliceDim4,
212 expected: [][][][]string{{{{"foo", "bar", "baz"}}}, {{{"wibble", "wobble", "wubble"}}}},
213 },
214 {
215 src: pgtype.TextArray{
216 Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}, {String: "bar", Status: pgtype.Present}},
217 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
218 Status: pgtype.Present},
219 dst: &stringArrayDim2,
220 expected: [2][1]string{{"foo"}, {"bar"}},
221 },
222 {
223 src: pgtype.TextArray{
224 Elements: []pgtype.Text{
225 {String: "foo", Status: pgtype.Present},
226 {String: "bar", Status: pgtype.Present},
227 {String: "baz", Status: pgtype.Present},
228 {String: "wibble", Status: pgtype.Present},
229 {String: "wobble", Status: pgtype.Present},
230 {String: "wubble", Status: pgtype.Present}},
231 Dimensions: []pgtype.ArrayDimension{
232 {LowerBound: 1, Length: 2},
233 {LowerBound: 1, Length: 1},
234 {LowerBound: 1, Length: 1},
235 {LowerBound: 1, Length: 3}},
236 Status: pgtype.Present},
237 dst: &stringArrayDim4,
238 expected: [2][1][1][3]string{{{{"foo", "bar", "baz"}}}, {{{"wibble", "wobble", "wubble"}}}},
239 },
240 }
241
242 for i, tt := range simpleTests {
243 err := tt.src.AssignTo(tt.dst)
244 if err != nil {
245 t.Errorf("%d: %v", i, err)
246 }
247
248 if dst := reflect.ValueOf(tt.dst).Elem().Interface(); !reflect.DeepEqual(dst, tt.expected) {
249 t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
250 }
251 }
252
253 errorTests := []struct {
254 src pgtype.TextArray
255 dst interface{}
256 }{
257 {
258 src: pgtype.TextArray{
259 Elements: []pgtype.Text{{Status: pgtype.Null}},
260 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
261 Status: pgtype.Present,
262 },
263 dst: &stringSlice,
264 },
265 {
266 src: pgtype.TextArray{
267 Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}, {String: "bar", Status: pgtype.Present}},
268 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}, {LowerBound: 1, Length: 2}},
269 Status: pgtype.Present},
270 dst: &stringArrayDim2,
271 },
272 {
273 src: pgtype.TextArray{
274 Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}, {String: "bar", Status: pgtype.Present}},
275 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}, {LowerBound: 1, Length: 2}},
276 Status: pgtype.Present},
277 dst: &stringSlice,
278 },
279 {
280 src: pgtype.TextArray{
281 Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}, {String: "bar", Status: pgtype.Present}},
282 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}},
283 Status: pgtype.Present},
284 dst: &stringArrayDim4,
285 },
286 }
287
288 for i, tt := range errorTests {
289 err := tt.src.AssignTo(tt.dst)
290 if err == nil {
291 t.Errorf("%d: expected error but none was returned (%v -> %v)", i, tt.src, tt.dst)
292 }
293 }
294 }
295
View as plain text