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