1// Code generated by erb. DO NOT EDIT. 2 3package pgtype 4 5import ( 6 "database/sql/driver" 7 "encoding/binary" 8 "fmt" 9 "reflect" 10 11 "github.com/jackc/pgio" 12) 13 14type TstzrangeArray struct { 15 Elements []Tstzrange 16 Dimensions []ArrayDimension 17 Status Status 18} 19 20func (dst *TstzrangeArray) Set(src interface{}) error { 21 // untyped nil and typed nil interfaces are different 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 // Attempt to match to select common types: 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 // Fallback to reflection if an optimised match was not found. 51 // The reflection is necessary for arrays and multidimensional slices, 52 // but it comes with a 20-50% performance penalty for large arrays/slices 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 // Maybe the target was one dimension too far, try again: 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 109func (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 143func (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 154func (src *TstzrangeArray) AssignTo(dst interface{}) error { 155 switch src.Status { 156 case Present: 157 if len(src.Dimensions) <= 1 { 158 // Attempt to match to select common types: 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 // Try to convert to something AssignTo can use directly. 174 if nextDst, retry := GetAssignToDstType(dst); retry { 175 return src.AssignTo(nextDst) 176 } 177 178 // Fallback to reflection if an optimised match was not found. 179 // The reflection is necessary for arrays and multidimensional slices, 180 // but it comes with a 20-50% performance penalty for large arrays/slices 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 215func (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 262func (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 298func (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 340func (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 // dimElemCounts is the multiples of elements that each array lies on. For 355 // example, a single dimension array of length 4 would have a dimElemCounts of 356 // [4]. A multi-dimensional array of lengths [3,5,2] would have a 357 // dimElemCounts of [30,10,2]. This is used to simplify when to render a '{' 358 // or '}'. 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 397func (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// Scan implements the database/sql Scanner interface. 442func (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// Value implements the database/sql/driver Valuer interface. 460func (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