github.com/jackc/pgx/v5@v5.5.5/pgtype/int.go.erb (about) 1 package pgtype 2 3 import ( 4 "database/sql/driver" 5 "encoding/binary" 6 "encoding/json" 7 "fmt" 8 "math" 9 "strconv" 10 11 "github.com/jackc/pgx/v5/internal/pgio" 12 ) 13 14 type Int64Scanner interface { 15 ScanInt64(Int8) error 16 } 17 18 type Int64Valuer interface { 19 Int64Value() (Int8, error) 20 } 21 22 23 <% [2, 4, 8].each do |pg_byte_size| %> 24 <% pg_bit_size = pg_byte_size * 8 %> 25 type Int<%= pg_byte_size %> struct { 26 Int<%= pg_bit_size %> int<%= pg_bit_size %> 27 Valid bool 28 } 29 30 // ScanInt64 implements the Int64Scanner interface. 31 func (dst *Int<%= pg_byte_size %>) ScanInt64(n Int8) error { 32 if !n.Valid { 33 *dst = Int<%= pg_byte_size %>{} 34 return nil 35 } 36 37 if n.Int64 < math.MinInt<%= pg_bit_size %> { 38 return fmt.Errorf("%d is less than minimum value for Int<%= pg_byte_size %>", n.Int64) 39 } 40 if n.Int64 > math.MaxInt<%= pg_bit_size %> { 41 return fmt.Errorf("%d is greater than maximum value for Int<%= pg_byte_size %>", n.Int64) 42 } 43 *dst = Int<%= pg_byte_size %>{Int<%= pg_bit_size %>: int<%= pg_bit_size %>(n.Int64), Valid: true} 44 45 return nil 46 } 47 48 func (n Int<%= pg_byte_size %>) Int64Value() (Int8, error) { 49 return Int8{Int64: int64(n.Int<%= pg_bit_size %>), Valid: n.Valid}, nil 50 } 51 52 // Scan implements the database/sql Scanner interface. 53 func (dst *Int<%= pg_byte_size %>) Scan(src any) error { 54 if src == nil { 55 *dst = Int<%= pg_byte_size %>{} 56 return nil 57 } 58 59 var n int64 60 61 switch src := src.(type) { 62 case int64: 63 n = src 64 case string: 65 var err error 66 n, err = strconv.ParseInt(src, 10, <%= pg_bit_size %>) 67 if err != nil { 68 return err 69 } 70 case []byte: 71 var err error 72 n, err = strconv.ParseInt(string(src), 10, <%= pg_bit_size %>) 73 if err != nil { 74 return err 75 } 76 default: 77 return fmt.Errorf("cannot scan %T", src) 78 } 79 80 if n < math.MinInt<%= pg_bit_size %> { 81 return fmt.Errorf("%d is greater than maximum value for Int<%= pg_byte_size %>", n) 82 } 83 if n > math.MaxInt<%= pg_bit_size %> { 84 return fmt.Errorf("%d is greater than maximum value for Int<%= pg_byte_size %>", n) 85 } 86 *dst = Int<%= pg_byte_size %>{Int<%= pg_bit_size %>: int<%= pg_bit_size %>(n), Valid: true} 87 88 return nil 89 } 90 91 // Value implements the database/sql/driver Valuer interface. 92 func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) { 93 if !src.Valid { 94 return nil, nil 95 } 96 return int64(src.Int<%= pg_bit_size %>), nil 97 } 98 99 func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) { 100 if !src.Valid { 101 return []byte("null"), nil 102 } 103 return []byte(strconv.FormatInt(int64(src.Int<%= pg_bit_size %>), 10)), nil 104 } 105 106 func (dst *Int<%= pg_byte_size %>) UnmarshalJSON(b []byte) error { 107 var n *int<%= pg_bit_size %> 108 err := json.Unmarshal(b, &n) 109 if err != nil { 110 return err 111 } 112 113 if n == nil { 114 *dst = Int<%= pg_byte_size %>{} 115 } else { 116 *dst = Int<%= pg_byte_size %>{Int<%= pg_bit_size %>: *n, Valid: true} 117 } 118 119 return nil 120 } 121 122 type Int<%= pg_byte_size %>Codec struct{} 123 124 func (Int<%= pg_byte_size %>Codec) FormatSupported(format int16) bool { 125 return format == TextFormatCode || format == BinaryFormatCode 126 } 127 128 func (Int<%= pg_byte_size %>Codec) PreferredFormat() int16 { 129 return BinaryFormatCode 130 } 131 132 func (Int<%= pg_byte_size %>Codec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan { 133 switch format { 134 case BinaryFormatCode: 135 switch value.(type) { 136 case int<%= pg_bit_size %>: 137 return encodePlanInt<%= pg_byte_size %>CodecBinaryInt<%= pg_bit_size %>{} 138 case Int64Valuer: 139 return encodePlanInt<%= pg_byte_size %>CodecBinaryInt64Valuer{} 140 } 141 case TextFormatCode: 142 switch value.(type) { 143 case int<%= pg_bit_size %>: 144 return encodePlanInt<%= pg_byte_size %>CodecTextInt<%= pg_bit_size %>{} 145 case Int64Valuer: 146 return encodePlanInt<%= pg_byte_size %>CodecTextInt64Valuer{} 147 } 148 } 149 150 return nil 151 } 152 153 type encodePlanInt<%= pg_byte_size %>CodecBinaryInt<%= pg_bit_size %> struct{} 154 155 func (encodePlanInt<%= pg_byte_size %>CodecBinaryInt<%= pg_bit_size %>) Encode(value any, buf []byte) (newBuf []byte, err error) { 156 n := value.(int<%= pg_bit_size %>) 157 return pgio.AppendInt<%= pg_bit_size %>(buf, int<%= pg_bit_size %>(n)), nil 158 } 159 160 type encodePlanInt<%= pg_byte_size %>CodecTextInt<%= pg_bit_size %> struct{} 161 162 func (encodePlanInt<%= pg_byte_size %>CodecTextInt<%= pg_bit_size %>) Encode(value any, buf []byte) (newBuf []byte, err error) { 163 n := value.(int<%= pg_bit_size %>) 164 return append(buf, strconv.FormatInt(int64(n), 10)...), nil 165 } 166 167 type encodePlanInt<%= pg_byte_size %>CodecBinaryInt64Valuer struct{} 168 169 func (encodePlanInt<%= pg_byte_size %>CodecBinaryInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) { 170 n, err := value.(Int64Valuer).Int64Value() 171 if err != nil { 172 return nil, err 173 } 174 175 if !n.Valid { 176 return nil, nil 177 } 178 179 if n.Int64 > math.MaxInt<%= pg_bit_size %> { 180 return nil, fmt.Errorf("%d is greater than maximum value for int<%= pg_byte_size %>", n.Int64) 181 } 182 if n.Int64 < math.MinInt<%= pg_bit_size %> { 183 return nil, fmt.Errorf("%d is less than minimum value for int<%= pg_byte_size %>", n.Int64) 184 } 185 186 return pgio.AppendInt<%= pg_bit_size %>(buf, int<%= pg_bit_size %>(n.Int64)), nil 187 } 188 189 type encodePlanInt<%= pg_byte_size %>CodecTextInt64Valuer struct{} 190 191 func (encodePlanInt<%= pg_byte_size %>CodecTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) { 192 n, err := value.(Int64Valuer).Int64Value() 193 if err != nil { 194 return nil, err 195 } 196 197 if !n.Valid { 198 return nil, nil 199 } 200 201 if n.Int64 > math.MaxInt<%= pg_bit_size %> { 202 return nil, fmt.Errorf("%d is greater than maximum value for int<%= pg_byte_size %>", n.Int64) 203 } 204 if n.Int64 < math.MinInt<%= pg_bit_size %> { 205 return nil, fmt.Errorf("%d is less than minimum value for int<%= pg_byte_size %>", n.Int64) 206 } 207 208 return append(buf, strconv.FormatInt(n.Int64, 10)...), nil 209 } 210 211 func (Int<%= pg_byte_size %>Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { 212 213 switch format { 214 case BinaryFormatCode: 215 switch target.(type) { 216 case *int8: 217 return scanPlanBinaryInt<%= pg_byte_size %>ToInt8{} 218 case *int16: 219 return scanPlanBinaryInt<%= pg_byte_size %>ToInt16{} 220 case *int32: 221 return scanPlanBinaryInt<%= pg_byte_size %>ToInt32{} 222 case *int64: 223 return scanPlanBinaryInt<%= pg_byte_size %>ToInt64{} 224 case *int: 225 return scanPlanBinaryInt<%= pg_byte_size %>ToInt{} 226 case *uint8: 227 return scanPlanBinaryInt<%= pg_byte_size %>ToUint8{} 228 case *uint16: 229 return scanPlanBinaryInt<%= pg_byte_size %>ToUint16{} 230 case *uint32: 231 return scanPlanBinaryInt<%= pg_byte_size %>ToUint32{} 232 case *uint64: 233 return scanPlanBinaryInt<%= pg_byte_size %>ToUint64{} 234 case *uint: 235 return scanPlanBinaryInt<%= pg_byte_size %>ToUint{} 236 case Int64Scanner: 237 return scanPlanBinaryInt<%= pg_byte_size %>ToInt64Scanner{} 238 case TextScanner: 239 return scanPlanBinaryInt<%= pg_byte_size %>ToTextScanner{} 240 } 241 case TextFormatCode: 242 switch target.(type) { 243 case *int8: 244 return scanPlanTextAnyToInt8{} 245 case *int16: 246 return scanPlanTextAnyToInt16{} 247 case *int32: 248 return scanPlanTextAnyToInt32{} 249 case *int64: 250 return scanPlanTextAnyToInt64{} 251 case *int: 252 return scanPlanTextAnyToInt{} 253 case *uint8: 254 return scanPlanTextAnyToUint8{} 255 case *uint16: 256 return scanPlanTextAnyToUint16{} 257 case *uint32: 258 return scanPlanTextAnyToUint32{} 259 case *uint64: 260 return scanPlanTextAnyToUint64{} 261 case *uint: 262 return scanPlanTextAnyToUint{} 263 case Int64Scanner: 264 return scanPlanTextAnyToInt64Scanner{} 265 } 266 } 267 268 return nil 269 } 270 271 func (c Int<%= pg_byte_size %>Codec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) { 272 if src == nil { 273 return nil, nil 274 } 275 276 var n int64 277 err := codecScan(c, m, oid, format, src, &n) 278 if err != nil { 279 return nil, err 280 } 281 return n, nil 282 } 283 284 func (c Int<%= pg_byte_size %>Codec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) { 285 if src == nil { 286 return nil, nil 287 } 288 289 var n int<%= pg_bit_size %> 290 err := codecScan(c, m, oid, format, src, &n) 291 if err != nil { 292 return nil, err 293 } 294 return n, nil 295 } 296 297 <%# PostgreSQL binary format integer to fixed size Go integers %> 298 <% [8, 16, 32, 64].each do |dst_bit_size| %> 299 type scanPlanBinaryInt<%= pg_byte_size %>ToInt<%= dst_bit_size %> struct{} 300 301 func (scanPlanBinaryInt<%= pg_byte_size %>ToInt<%= dst_bit_size %>) Scan(src []byte, dst any) error { 302 if src == nil { 303 return fmt.Errorf("cannot scan NULL into %T", dst) 304 } 305 306 if len(src) != <%= pg_byte_size %> { 307 return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src)) 308 } 309 310 p, ok := (dst).(*int<%= dst_bit_size %>) 311 if !ok { 312 return ErrScanTargetTypeChanged 313 } 314 315 <% if dst_bit_size < pg_bit_size %> 316 n := int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)) 317 if n < math.MinInt<%= dst_bit_size %> { 318 return fmt.Errorf("%d is less than minimum value for int<%= dst_bit_size %>", n) 319 } else if n > math.MaxInt<%= dst_bit_size %> { 320 return fmt.Errorf("%d is greater than maximum value for int<%= dst_bit_size %>", n) 321 } 322 323 *p = int<%= dst_bit_size %>(n) 324 <% elsif dst_bit_size == pg_bit_size %> 325 *p = int<%= dst_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)) 326 <% else %> 327 *p = int<%= dst_bit_size %>(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src))) 328 <% end %> 329 330 return nil 331 } 332 333 type scanPlanBinaryInt<%= pg_byte_size %>ToUint<%= dst_bit_size %> struct{} 334 335 func (scanPlanBinaryInt<%= pg_byte_size %>ToUint<%= dst_bit_size %>) Scan(src []byte, dst any) error { 336 if src == nil { 337 return fmt.Errorf("cannot scan NULL into %T", dst) 338 } 339 340 if len(src) != <%= pg_byte_size %> { 341 return fmt.Errorf("invalid length for uint<%= pg_byte_size %>: %v", len(src)) 342 } 343 344 p, ok := (dst).(*uint<%= dst_bit_size %>) 345 if !ok { 346 return ErrScanTargetTypeChanged 347 } 348 349 n := int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)) 350 if n < 0 { 351 return fmt.Errorf("%d is less than minimum value for uint<%= dst_bit_size %>", n) 352 } 353 <% if dst_bit_size < pg_bit_size %> 354 if n > math.MaxUint<%= dst_bit_size %> { 355 return fmt.Errorf("%d is greater than maximum value for uint<%= dst_bit_size %>", n) 356 } 357 <% end %> 358 *p = uint<%= dst_bit_size %>(n) 359 360 return nil 361 } 362 <% end %> 363 364 <%# PostgreSQL binary format integer to Go machine integers %> 365 type scanPlanBinaryInt<%= pg_byte_size %>ToInt struct{} 366 367 func (scanPlanBinaryInt<%= pg_byte_size %>ToInt) Scan(src []byte, dst any) error { 368 if src == nil { 369 return fmt.Errorf("cannot scan NULL into %T", dst) 370 } 371 372 if len(src) != <%= pg_byte_size %> { 373 return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src)) 374 } 375 376 p, ok := (dst).(*int) 377 if !ok { 378 return ErrScanTargetTypeChanged 379 } 380 381 <% if 32 < pg_bit_size %> 382 n := int64(binary.BigEndian.Uint<%= pg_bit_size %>(src)) 383 if n < math.MinInt { 384 return fmt.Errorf("%d is less than minimum value for int", n) 385 } else if n > math.MaxInt { 386 return fmt.Errorf("%d is greater than maximum value for int", n) 387 } 388 389 *p = int(n) 390 <% else %> 391 *p = int(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src))) 392 <% end %> 393 394 return nil 395 } 396 397 type scanPlanBinaryInt<%= pg_byte_size %>ToUint struct{} 398 399 func (scanPlanBinaryInt<%= pg_byte_size %>ToUint) Scan(src []byte, dst any) error { 400 if src == nil { 401 return fmt.Errorf("cannot scan NULL into %T", dst) 402 } 403 404 if len(src) != <%= pg_byte_size %> { 405 return fmt.Errorf("invalid length for uint<%= pg_byte_size %>: %v", len(src)) 406 } 407 408 p, ok := (dst).(*uint) 409 if !ok { 410 return ErrScanTargetTypeChanged 411 } 412 413 n := int64(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src))) 414 if n < 0 { 415 return fmt.Errorf("%d is less than minimum value for uint", n) 416 } 417 <% if 32 < pg_bit_size %> 418 if uint64(n) > math.MaxUint { 419 return fmt.Errorf("%d is greater than maximum value for uint", n) 420 } 421 <% end %> 422 *p = uint(n) 423 424 return nil 425 } 426 427 <%# PostgreSQL binary format integer to Go Int64Scanner %> 428 type scanPlanBinaryInt<%= pg_byte_size %>ToInt64Scanner struct{} 429 430 func (scanPlanBinaryInt<%= pg_byte_size %>ToInt64Scanner) Scan(src []byte, dst any) error { 431 s, ok := (dst).(Int64Scanner) 432 if !ok { 433 return ErrScanTargetTypeChanged 434 } 435 436 if src == nil { 437 return s.ScanInt64(Int8{}) 438 } 439 440 if len(src) != <%= pg_byte_size %> { 441 return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src)) 442 } 443 444 445 n := int64(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src))) 446 447 return s.ScanInt64(Int8{Int64: n, Valid: true}) 448 } 449 450 <%# PostgreSQL binary format integer to Go TextScanner %> 451 type scanPlanBinaryInt<%= pg_byte_size %>ToTextScanner struct{} 452 453 func (scanPlanBinaryInt<%= pg_byte_size %>ToTextScanner) Scan(src []byte, dst any) error { 454 s, ok := (dst).(TextScanner) 455 if !ok { 456 return ErrScanTargetTypeChanged 457 } 458 459 if src == nil { 460 return s.ScanText(Text{}) 461 } 462 463 if len(src) != <%= pg_byte_size %> { 464 return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src)) 465 } 466 467 468 n := int64(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src))) 469 470 return s.ScanText(Text{String: strconv.FormatInt(n, 10), Valid: true}) 471 } 472 <% end %> 473 474 <%# Any text to all integer types %> 475 <% [ 476 ["8", 8], 477 ["16", 16], 478 ["32", 32], 479 ["64", 64], 480 ["", 0] 481 ].each do |type_suffix, bit_size| %> 482 type scanPlanTextAnyToInt<%= type_suffix %> struct{} 483 484 func (scanPlanTextAnyToInt<%= type_suffix %>) Scan(src []byte, dst any) error { 485 if src == nil { 486 return fmt.Errorf("cannot scan NULL into %T", dst) 487 } 488 489 p, ok := (dst).(*int<%= type_suffix %>) 490 if !ok { 491 return ErrScanTargetTypeChanged 492 } 493 494 n, err := strconv.ParseInt(string(src), 10, <%= bit_size %>) 495 if err != nil { 496 return err 497 } 498 499 *p = int<%= type_suffix %>(n) 500 return nil 501 } 502 503 type scanPlanTextAnyToUint<%= type_suffix %> struct{} 504 505 func (scanPlanTextAnyToUint<%= type_suffix %>) Scan(src []byte, dst any) error { 506 if src == nil { 507 return fmt.Errorf("cannot scan NULL into %T", dst) 508 } 509 510 p, ok := (dst).(*uint<%= type_suffix %>) 511 if !ok { 512 return ErrScanTargetTypeChanged 513 } 514 515 n, err := strconv.ParseUint(string(src), 10, <%= bit_size %>) 516 if err != nil { 517 return err 518 } 519 520 *p = uint<%= type_suffix %>(n) 521 return nil 522 } 523 <% end %> 524 525 type scanPlanTextAnyToInt64Scanner struct{} 526 527 func (scanPlanTextAnyToInt64Scanner) Scan(src []byte, dst any) error { 528 s, ok := (dst).(Int64Scanner) 529 if !ok { 530 return ErrScanTargetTypeChanged 531 } 532 533 if src == nil { 534 return s.ScanInt64(Int8{}) 535 } 536 537 n, err := strconv.ParseInt(string(src), 10, 64) 538 if err != nil { 539 return err 540 } 541 542 err = s.ScanInt64(Int8{Int64: n, Valid: true}) 543 if err != nil { 544 return err 545 } 546 547 return nil 548 }