1
2
3 package pgtype
4
5 import (
6 "database/sql/driver"
7 "fmt"
8 "reflect"
9 )
10
11 type ACLItemArray struct {
12 Elements []ACLItem
13 Dimensions []ArrayDimension
14 Status Status
15 }
16
17 func (dst *ACLItemArray) Set(src interface{}) error {
18
19 if src == nil {
20 *dst = ACLItemArray{Status: Null}
21 return nil
22 }
23
24 if value, ok := src.(interface{ Get() interface{} }); ok {
25 value2 := value.Get()
26 if value2 != value {
27 return dst.Set(value2)
28 }
29 }
30
31
32 switch value := src.(type) {
33
34 case []string:
35 if value == nil {
36 *dst = ACLItemArray{Status: Null}
37 } else if len(value) == 0 {
38 *dst = ACLItemArray{Status: Present}
39 } else {
40 elements := make([]ACLItem, len(value))
41 for i := range value {
42 if err := elements[i].Set(value[i]); err != nil {
43 return err
44 }
45 }
46 *dst = ACLItemArray{
47 Elements: elements,
48 Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
49 Status: Present,
50 }
51 }
52
53 case []*string:
54 if value == nil {
55 *dst = ACLItemArray{Status: Null}
56 } else if len(value) == 0 {
57 *dst = ACLItemArray{Status: Present}
58 } else {
59 elements := make([]ACLItem, len(value))
60 for i := range value {
61 if err := elements[i].Set(value[i]); err != nil {
62 return err
63 }
64 }
65 *dst = ACLItemArray{
66 Elements: elements,
67 Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
68 Status: Present,
69 }
70 }
71
72 case []ACLItem:
73 if value == nil {
74 *dst = ACLItemArray{Status: Null}
75 } else if len(value) == 0 {
76 *dst = ACLItemArray{Status: Present}
77 } else {
78 *dst = ACLItemArray{
79 Elements: value,
80 Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
81 Status: Present,
82 }
83 }
84 default:
85
86
87
88 reflectedValue := reflect.ValueOf(src)
89 if !reflectedValue.IsValid() || reflectedValue.IsZero() {
90 *dst = ACLItemArray{Status: Null}
91 return nil
92 }
93
94 dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
95 if !ok {
96 return fmt.Errorf("cannot find dimensions of %v for ACLItemArray", src)
97 }
98 if elementsLength == 0 {
99 *dst = ACLItemArray{Status: Present}
100 return nil
101 }
102 if len(dimensions) == 0 {
103 if originalSrc, ok := underlyingSliceType(src); ok {
104 return dst.Set(originalSrc)
105 }
106 return fmt.Errorf("cannot convert %v to ACLItemArray", src)
107 }
108
109 *dst = ACLItemArray{
110 Elements: make([]ACLItem, elementsLength),
111 Dimensions: dimensions,
112 Status: Present,
113 }
114 elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
115 if err != nil {
116
117 if len(dst.Dimensions) > 1 {
118 dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
119 elementsLength = 0
120 for _, dim := range dst.Dimensions {
121 if elementsLength == 0 {
122 elementsLength = int(dim.Length)
123 } else {
124 elementsLength *= int(dim.Length)
125 }
126 }
127 dst.Elements = make([]ACLItem, elementsLength)
128 elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
129 if err != nil {
130 return err
131 }
132 } else {
133 return err
134 }
135 }
136 if elementCount != len(dst.Elements) {
137 return fmt.Errorf("cannot convert %v to ACLItemArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
138 }
139 }
140
141 return nil
142 }
143
144 func (dst *ACLItemArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
145 switch value.Kind() {
146 case reflect.Array:
147 fallthrough
148 case reflect.Slice:
149 if len(dst.Dimensions) == dimension {
150 break
151 }
152
153 valueLen := value.Len()
154 if int32(valueLen) != dst.Dimensions[dimension].Length {
155 return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
156 }
157 for i := 0; i < valueLen; i++ {
158 var err error
159 index, err = dst.setRecursive(value.Index(i), index, dimension+1)
160 if err != nil {
161 return 0, err
162 }
163 }
164
165 return index, nil
166 }
167 if !value.CanInterface() {
168 return 0, fmt.Errorf("cannot convert all values to ACLItemArray")
169 }
170 if err := dst.Elements[index].Set(value.Interface()); err != nil {
171 return 0, fmt.Errorf("%v in ACLItemArray", err)
172 }
173 index++
174
175 return index, nil
176 }
177
178 func (dst ACLItemArray) Get() interface{} {
179 switch dst.Status {
180 case Present:
181 return dst
182 case Null:
183 return nil
184 default:
185 return dst.Status
186 }
187 }
188
189 func (src *ACLItemArray) AssignTo(dst interface{}) error {
190 switch src.Status {
191 case Present:
192 if len(src.Dimensions) <= 1 {
193
194 switch v := dst.(type) {
195
196 case *[]string:
197 *v = make([]string, len(src.Elements))
198 for i := range src.Elements {
199 if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
200 return err
201 }
202 }
203 return nil
204
205 case *[]*string:
206 *v = make([]*string, len(src.Elements))
207 for i := range src.Elements {
208 if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
209 return err
210 }
211 }
212 return nil
213
214 }
215 }
216
217
218 if nextDst, retry := GetAssignToDstType(dst); retry {
219 return src.AssignTo(nextDst)
220 }
221
222
223
224
225 value := reflect.ValueOf(dst)
226 if value.Kind() == reflect.Ptr {
227 value = value.Elem()
228 }
229
230 switch value.Kind() {
231 case reflect.Array, reflect.Slice:
232 default:
233 return fmt.Errorf("cannot assign %T to %T", src, dst)
234 }
235
236 if len(src.Elements) == 0 {
237 if value.Kind() == reflect.Slice {
238 value.Set(reflect.MakeSlice(value.Type(), 0, 0))
239 return nil
240 }
241 }
242
243 elementCount, err := src.assignToRecursive(value, 0, 0)
244 if err != nil {
245 return err
246 }
247 if elementCount != len(src.Elements) {
248 return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
249 }
250
251 return nil
252 case Null:
253 return NullAssignTo(dst)
254 }
255
256 return fmt.Errorf("cannot decode %#v into %T", src, dst)
257 }
258
259 func (src *ACLItemArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
260 switch kind := value.Kind(); kind {
261 case reflect.Array:
262 fallthrough
263 case reflect.Slice:
264 if len(src.Dimensions) == dimension {
265 break
266 }
267
268 length := int(src.Dimensions[dimension].Length)
269 if reflect.Array == kind {
270 typ := value.Type()
271 if typ.Len() != length {
272 return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
273 }
274 value.Set(reflect.New(typ).Elem())
275 } else {
276 value.Set(reflect.MakeSlice(value.Type(), length, length))
277 }
278
279 var err error
280 for i := 0; i < length; i++ {
281 index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
282 if err != nil {
283 return 0, err
284 }
285 }
286
287 return index, nil
288 }
289 if len(src.Dimensions) != dimension {
290 return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
291 }
292 if !value.CanAddr() {
293 return 0, fmt.Errorf("cannot assign all values from ACLItemArray")
294 }
295 addr := value.Addr()
296 if !addr.CanInterface() {
297 return 0, fmt.Errorf("cannot assign all values from ACLItemArray")
298 }
299 if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
300 return 0, err
301 }
302 index++
303 return index, nil
304 }
305
306 func (dst *ACLItemArray) DecodeText(ci *ConnInfo, src []byte) error {
307 if src == nil {
308 *dst = ACLItemArray{Status: Null}
309 return nil
310 }
311
312 uta, err := ParseUntypedTextArray(string(src))
313 if err != nil {
314 return err
315 }
316
317 var elements []ACLItem
318
319 if len(uta.Elements) > 0 {
320 elements = make([]ACLItem, len(uta.Elements))
321
322 for i, s := range uta.Elements {
323 var elem ACLItem
324 var elemSrc []byte
325 if s != "NULL" || uta.Quoted[i] {
326 elemSrc = []byte(s)
327 }
328 err = elem.DecodeText(ci, elemSrc)
329 if err != nil {
330 return err
331 }
332
333 elements[i] = elem
334 }
335 }
336
337 *dst = ACLItemArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
338
339 return nil
340 }
341
342 func (src ACLItemArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
343 switch src.Status {
344 case Null:
345 return nil, nil
346 case Undefined:
347 return nil, errUndefined
348 }
349
350 if len(src.Dimensions) == 0 {
351 return append(buf, '{', '}'), nil
352 }
353
354 buf = EncodeTextArrayDimensions(buf, src.Dimensions)
355
356
357
358
359
360
361 dimElemCounts := make([]int, len(src.Dimensions))
362 dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
363 for i := len(src.Dimensions) - 2; i > -1; i-- {
364 dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
365 }
366
367 inElemBuf := make([]byte, 0, 32)
368 for i, elem := range src.Elements {
369 if i > 0 {
370 buf = append(buf, ',')
371 }
372
373 for _, dec := range dimElemCounts {
374 if i%dec == 0 {
375 buf = append(buf, '{')
376 }
377 }
378
379 elemBuf, err := elem.EncodeText(ci, inElemBuf)
380 if err != nil {
381 return nil, err
382 }
383 if elemBuf == nil {
384 buf = append(buf, `NULL`...)
385 } else {
386 buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
387 }
388
389 for _, dec := range dimElemCounts {
390 if (i+1)%dec == 0 {
391 buf = append(buf, '}')
392 }
393 }
394 }
395
396 return buf, nil
397 }
398
399
400 func (dst *ACLItemArray) Scan(src interface{}) error {
401 if src == nil {
402 return dst.DecodeText(nil, nil)
403 }
404
405 switch src := src.(type) {
406 case string:
407 return dst.DecodeText(nil, []byte(src))
408 case []byte:
409 srcCopy := make([]byte, len(src))
410 copy(srcCopy, src)
411 return dst.DecodeText(nil, srcCopy)
412 }
413
414 return fmt.Errorf("cannot scan %T", src)
415 }
416
417
418 func (src ACLItemArray) Value() (driver.Value, error) {
419 buf, err := src.EncodeText(nil, nil)
420 if err != nil {
421 return nil, err
422 }
423 if buf == nil {
424 return nil, nil
425 }
426
427 return string(buf), nil
428 }
429
View as plain text