1package pgtype
2
3import (
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
14type Int64Scanner interface {
15 ScanInt64(Int8) error
16}
17
18type 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 %>
25type 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.
31func (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
48func (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.
53func (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.
92func (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
99func (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
106func (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
122type Int<%= pg_byte_size %>Codec struct{}
123
124func (Int<%= pg_byte_size %>Codec) FormatSupported(format int16) bool {
125 return format == TextFormatCode || format == BinaryFormatCode
126}
127
128func (Int<%= pg_byte_size %>Codec) PreferredFormat() int16 {
129 return BinaryFormatCode
130}
131
132func (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
153type encodePlanInt<%= pg_byte_size %>CodecBinaryInt<%= pg_bit_size %> struct{}
154
155func (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
160type encodePlanInt<%= pg_byte_size %>CodecTextInt<%= pg_bit_size %> struct{}
161
162func (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
167type encodePlanInt<%= pg_byte_size %>CodecBinaryInt64Valuer struct{}
168
169func (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
189type encodePlanInt<%= pg_byte_size %>CodecTextInt64Valuer struct{}
190
191func (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
211func (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
271func (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
284func (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| %>
299type scanPlanBinaryInt<%= pg_byte_size %>ToInt<%= dst_bit_size %> struct{}
300
301func (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
333type scanPlanBinaryInt<%= pg_byte_size %>ToUint<%= dst_bit_size %> struct{}
334
335func (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 %>
365type scanPlanBinaryInt<%= pg_byte_size %>ToInt struct{}
366
367func (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
397type scanPlanBinaryInt<%= pg_byte_size %>ToUint struct{}
398
399func (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 %>
428type scanPlanBinaryInt<%= pg_byte_size %>ToInt64Scanner struct{}
429
430func (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 %>
451type scanPlanBinaryInt<%= pg_byte_size %>ToTextScanner struct{}
452
453func (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| %>
482type scanPlanTextAnyToInt<%= type_suffix %> struct{}
483
484func (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
503type scanPlanTextAnyToUint<%= type_suffix %> struct{}
504
505func (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
525type scanPlanTextAnyToInt64Scanner struct{}
526
527func (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}
View as plain text