1 package pgtype
2
3 import (
4 "database/sql/driver"
5 "encoding/binary"
6 "fmt"
7 "strconv"
8 "strings"
9
10 "github.com/jackc/pgio"
11 )
12
13
14
15
16
17
18
19
20
21
22
23
24 type TID struct {
25 BlockNumber uint32
26 OffsetNumber uint16
27 Status Status
28 }
29
30 func (dst *TID) Set(src interface{}) error {
31 return fmt.Errorf("cannot convert %v to TID", src)
32 }
33
34 func (dst TID) Get() interface{} {
35 switch dst.Status {
36 case Present:
37 return dst
38 case Null:
39 return nil
40 default:
41 return dst.Status
42 }
43 }
44
45 func (src *TID) AssignTo(dst interface{}) error {
46 if src.Status == Present {
47 switch v := dst.(type) {
48 case *string:
49 *v = fmt.Sprintf(`(%d,%d)`, src.BlockNumber, src.OffsetNumber)
50 return nil
51 default:
52 if nextDst, retry := GetAssignToDstType(dst); retry {
53 return src.AssignTo(nextDst)
54 }
55 return fmt.Errorf("unable to assign to %T", dst)
56 }
57 }
58
59 return fmt.Errorf("cannot assign %v to %T", src, dst)
60 }
61
62 func (dst *TID) DecodeText(ci *ConnInfo, src []byte) error {
63 if src == nil {
64 *dst = TID{Status: Null}
65 return nil
66 }
67
68 if len(src) < 5 {
69 return fmt.Errorf("invalid length for tid: %v", len(src))
70 }
71
72 parts := strings.SplitN(string(src[1:len(src)-1]), ",", 2)
73 if len(parts) < 2 {
74 return fmt.Errorf("invalid format for tid")
75 }
76
77 blockNumber, err := strconv.ParseUint(parts[0], 10, 32)
78 if err != nil {
79 return err
80 }
81
82 offsetNumber, err := strconv.ParseUint(parts[1], 10, 16)
83 if err != nil {
84 return err
85 }
86
87 *dst = TID{BlockNumber: uint32(blockNumber), OffsetNumber: uint16(offsetNumber), Status: Present}
88 return nil
89 }
90
91 func (dst *TID) DecodeBinary(ci *ConnInfo, src []byte) error {
92 if src == nil {
93 *dst = TID{Status: Null}
94 return nil
95 }
96
97 if len(src) != 6 {
98 return fmt.Errorf("invalid length for tid: %v", len(src))
99 }
100
101 *dst = TID{
102 BlockNumber: binary.BigEndian.Uint32(src),
103 OffsetNumber: binary.BigEndian.Uint16(src[4:]),
104 Status: Present,
105 }
106 return nil
107 }
108
109 func (src TID) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
110 switch src.Status {
111 case Null:
112 return nil, nil
113 case Undefined:
114 return nil, errUndefined
115 }
116
117 buf = append(buf, fmt.Sprintf(`(%d,%d)`, src.BlockNumber, src.OffsetNumber)...)
118 return buf, nil
119 }
120
121 func (src TID) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
122 switch src.Status {
123 case Null:
124 return nil, nil
125 case Undefined:
126 return nil, errUndefined
127 }
128
129 buf = pgio.AppendUint32(buf, src.BlockNumber)
130 buf = pgio.AppendUint16(buf, src.OffsetNumber)
131 return buf, nil
132 }
133
134
135 func (dst *TID) Scan(src interface{}) error {
136 if src == nil {
137 *dst = TID{Status: Null}
138 return nil
139 }
140
141 switch src := src.(type) {
142 case string:
143 return dst.DecodeText(nil, []byte(src))
144 case []byte:
145 srcCopy := make([]byte, len(src))
146 copy(srcCopy, src)
147 return dst.DecodeText(nil, srcCopy)
148 }
149
150 return fmt.Errorf("cannot scan %T", src)
151 }
152
153
154 func (src TID) Value() (driver.Value, error) {
155 return EncodeValueText(src)
156 }
157
View as plain text