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