github.com/jackc/pgx/v5@v5.5.5/pgtype/range.go (about) 1 package pgtype 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 ) 8 9 type BoundType byte 10 11 const ( 12 Inclusive = BoundType('i') 13 Exclusive = BoundType('e') 14 Unbounded = BoundType('U') 15 Empty = BoundType('E') 16 ) 17 18 func (bt BoundType) String() string { 19 return string(bt) 20 } 21 22 type untypedTextRange struct { 23 Lower string 24 Upper string 25 LowerType BoundType 26 UpperType BoundType 27 } 28 29 func parseUntypedTextRange(src string) (*untypedTextRange, error) { 30 utr := &untypedTextRange{} 31 if src == "empty" { 32 utr.LowerType = Empty 33 utr.UpperType = Empty 34 return utr, nil 35 } 36 37 buf := bytes.NewBufferString(src) 38 39 skipWhitespace(buf) 40 41 r, _, err := buf.ReadRune() 42 if err != nil { 43 return nil, fmt.Errorf("invalid lower bound: %w", err) 44 } 45 switch r { 46 case '(': 47 utr.LowerType = Exclusive 48 case '[': 49 utr.LowerType = Inclusive 50 default: 51 return nil, fmt.Errorf("missing lower bound, instead got: %v", string(r)) 52 } 53 54 r, _, err = buf.ReadRune() 55 if err != nil { 56 return nil, fmt.Errorf("invalid lower value: %w", err) 57 } 58 buf.UnreadRune() 59 60 if r == ',' { 61 utr.LowerType = Unbounded 62 } else { 63 utr.Lower, err = rangeParseValue(buf) 64 if err != nil { 65 return nil, fmt.Errorf("invalid lower value: %w", err) 66 } 67 } 68 69 r, _, err = buf.ReadRune() 70 if err != nil { 71 return nil, fmt.Errorf("missing range separator: %w", err) 72 } 73 if r != ',' { 74 return nil, fmt.Errorf("missing range separator: %v", r) 75 } 76 77 r, _, err = buf.ReadRune() 78 if err != nil { 79 return nil, fmt.Errorf("invalid upper value: %w", err) 80 } 81 82 if r == ')' || r == ']' { 83 utr.UpperType = Unbounded 84 } else { 85 buf.UnreadRune() 86 utr.Upper, err = rangeParseValue(buf) 87 if err != nil { 88 return nil, fmt.Errorf("invalid upper value: %w", err) 89 } 90 91 r, _, err = buf.ReadRune() 92 if err != nil { 93 return nil, fmt.Errorf("missing upper bound: %w", err) 94 } 95 switch r { 96 case ')': 97 utr.UpperType = Exclusive 98 case ']': 99 utr.UpperType = Inclusive 100 default: 101 return nil, fmt.Errorf("missing upper bound, instead got: %v", string(r)) 102 } 103 } 104 105 skipWhitespace(buf) 106 107 if buf.Len() > 0 { 108 return nil, fmt.Errorf("unexpected trailing data: %v", buf.String()) 109 } 110 111 return utr, nil 112 } 113 114 func rangeParseValue(buf *bytes.Buffer) (string, error) { 115 r, _, err := buf.ReadRune() 116 if err != nil { 117 return "", err 118 } 119 if r == '"' { 120 return rangeParseQuotedValue(buf) 121 } 122 buf.UnreadRune() 123 124 s := &bytes.Buffer{} 125 126 for { 127 r, _, err := buf.ReadRune() 128 if err != nil { 129 return "", err 130 } 131 132 switch r { 133 case '\\': 134 r, _, err = buf.ReadRune() 135 if err != nil { 136 return "", err 137 } 138 case ',', '[', ']', '(', ')': 139 buf.UnreadRune() 140 return s.String(), nil 141 } 142 143 s.WriteRune(r) 144 } 145 } 146 147 func rangeParseQuotedValue(buf *bytes.Buffer) (string, error) { 148 s := &bytes.Buffer{} 149 150 for { 151 r, _, err := buf.ReadRune() 152 if err != nil { 153 return "", err 154 } 155 156 switch r { 157 case '\\': 158 r, _, err = buf.ReadRune() 159 if err != nil { 160 return "", err 161 } 162 case '"': 163 r, _, err = buf.ReadRune() 164 if err != nil { 165 return "", err 166 } 167 if r != '"' { 168 buf.UnreadRune() 169 return s.String(), nil 170 } 171 } 172 s.WriteRune(r) 173 } 174 } 175 176 type untypedBinaryRange struct { 177 Lower []byte 178 Upper []byte 179 LowerType BoundType 180 UpperType BoundType 181 } 182 183 // 0 = () = 00000 184 // 1 = empty = 00001 185 // 2 = [) = 00010 186 // 4 = (] = 00100 187 // 6 = [] = 00110 188 // 8 = ) = 01000 189 // 12 = ] = 01100 190 // 16 = ( = 10000 191 // 18 = [ = 10010 192 // 24 = = 11000 193 194 const emptyMask = 1 195 const lowerInclusiveMask = 2 196 const upperInclusiveMask = 4 197 const lowerUnboundedMask = 8 198 const upperUnboundedMask = 16 199 200 func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) { 201 ubr := &untypedBinaryRange{} 202 203 if len(src) == 0 { 204 return nil, fmt.Errorf("range too short: %v", len(src)) 205 } 206 207 rangeType := src[0] 208 rp := 1 209 210 if rangeType&emptyMask > 0 { 211 if len(src[rp:]) > 0 { 212 return nil, fmt.Errorf("unexpected trailing bytes parsing empty range: %v", len(src[rp:])) 213 } 214 ubr.LowerType = Empty 215 ubr.UpperType = Empty 216 return ubr, nil 217 } 218 219 if rangeType&lowerInclusiveMask > 0 { 220 ubr.LowerType = Inclusive 221 } else if rangeType&lowerUnboundedMask > 0 { 222 ubr.LowerType = Unbounded 223 } else { 224 ubr.LowerType = Exclusive 225 } 226 227 if rangeType&upperInclusiveMask > 0 { 228 ubr.UpperType = Inclusive 229 } else if rangeType&upperUnboundedMask > 0 { 230 ubr.UpperType = Unbounded 231 } else { 232 ubr.UpperType = Exclusive 233 } 234 235 if ubr.LowerType == Unbounded && ubr.UpperType == Unbounded { 236 if len(src[rp:]) > 0 { 237 return nil, fmt.Errorf("unexpected trailing bytes parsing unbounded range: %v", len(src[rp:])) 238 } 239 return ubr, nil 240 } 241 242 if len(src[rp:]) < 4 { 243 return nil, fmt.Errorf("too few bytes for size: %v", src[rp:]) 244 } 245 valueLen := int(binary.BigEndian.Uint32(src[rp:])) 246 rp += 4 247 248 val := src[rp : rp+valueLen] 249 rp += valueLen 250 251 if ubr.LowerType != Unbounded { 252 ubr.Lower = val 253 } else { 254 ubr.Upper = val 255 if len(src[rp:]) > 0 { 256 return nil, fmt.Errorf("unexpected trailing bytes parsing range: %v", len(src[rp:])) 257 } 258 return ubr, nil 259 } 260 261 if ubr.UpperType != Unbounded { 262 if len(src[rp:]) < 4 { 263 return nil, fmt.Errorf("too few bytes for size: %v", src[rp:]) 264 } 265 valueLen := int(binary.BigEndian.Uint32(src[rp:])) 266 rp += 4 267 ubr.Upper = src[rp : rp+valueLen] 268 rp += valueLen 269 } 270 271 if len(src[rp:]) > 0 { 272 return nil, fmt.Errorf("unexpected trailing bytes parsing range: %v", len(src[rp:])) 273 } 274 275 return ubr, nil 276 277 } 278 279 // Range is a generic range type. 280 type Range[T any] struct { 281 Lower T 282 Upper T 283 LowerType BoundType 284 UpperType BoundType 285 Valid bool 286 } 287 288 func (r Range[T]) IsNull() bool { 289 return !r.Valid 290 } 291 292 func (r Range[T]) BoundTypes() (lower, upper BoundType) { 293 return r.LowerType, r.UpperType 294 } 295 296 func (r Range[T]) Bounds() (lower, upper any) { 297 return &r.Lower, &r.Upper 298 } 299 300 func (r *Range[T]) ScanNull() error { 301 *r = Range[T]{} 302 return nil 303 } 304 305 func (r *Range[T]) ScanBounds() (lowerTarget, upperTarget any) { 306 return &r.Lower, &r.Upper 307 } 308 309 func (r *Range[T]) SetBoundTypes(lower, upper BoundType) error { 310 if lower == Unbounded || lower == Empty { 311 var zero T 312 r.Lower = zero 313 } 314 if upper == Unbounded || upper == Empty { 315 var zero T 316 r.Upper = zero 317 } 318 r.LowerType = lower 319 r.UpperType = upper 320 r.Valid = true 321 return nil 322 }