Passed
Pull Request — master (#2447)
by Tolga
03:35
created

postgres.pguint64.Value   A

Complexity

Conditions 4

Size

Total Lines 8
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
package postgres
2
3
import (
4
	"database/sql/driver"
5
	"encoding/binary"
6
	"errors"
7
	"fmt"
8
	"strconv"
9
10
	"github.com/jackc/pgio"
11
	"github.com/jackc/pgtype"
12
)
13
14
// pguint64 represents a PostgreSQL uint64 type
15
type pguint64 struct {
16
	Uint   uint64
17
	Status pgtype.Status
18
}
19
20
// Set sets the pguint64 value from various input types
21
func (p *pguint64) Set(src interface{}) error {
22
	switch value := src.(type) {
23
	case int64:
24
		if value < 0 {
25
			return fmt.Errorf("%d is less than minimum value for pguint64", value)
26
		}
27
		*p = pguint64{Uint: uint64(value), Status: pgtype.Present}
28
	case int32:
29
		if value < 0 {
30
			return fmt.Errorf("%d is less than minimum value for pguint64", value)
31
		}
32
		*p = pguint64{Uint: uint64(value), Status: pgtype.Present}
33
	case uint32:
34
		*p = pguint64{Uint: uint64(value), Status: pgtype.Present}
35
	case uint64:
36
		*p = pguint64{Uint: value, Status: pgtype.Present}
37
	default:
38
		return fmt.Errorf("cannot convert %v to pguint64", value)
39
	}
40
41
	return nil
42
}
43
44
// Get returns the underlying value
45
func (p pguint64) Get() interface{} {
46
	switch p.Status {
47
	case pgtype.Present:
48
		return p.Uint
49
	case pgtype.Null:
50
		return nil
51
	default:
52
		return p.Status
53
	}
54
}
55
56
// AssignTo assigns the value to the destination
57
func (p *pguint64) AssignTo(dst interface{}) error {
58
	switch v := dst.(type) {
59
	case *uint64:
60
		if p.Status == pgtype.Present {
61
			*v = p.Uint
62
		} else {
63
			return fmt.Errorf("cannot assign %v into %T", p, dst)
64
		}
65
	case **uint64:
66
		if p.Status == pgtype.Present {
67
			n := p.Uint
68
			*v = &n
69
		} else {
70
			*v = nil
71
		}
72
	}
73
74
	return nil
75
}
76
77
// DecodeText decodes text format
78
func (p *pguint64) DecodeText(ci *pgtype.ConnInfo, src []byte) error {
79
	if src == nil {
80
		*p = pguint64{Status: pgtype.Null}
81
		return nil
82
	}
83
84
	n, err := strconv.ParseUint(string(src), 10, 64)
85
	if err != nil {
86
		return err
87
	}
88
89
	*p = pguint64{Uint: n, Status: pgtype.Present}
90
	return nil
91
}
92
93
// DecodeBinary decodes binary format
94
func (p *pguint64) DecodeBinary(ci *pgtype.ConnInfo, src []byte) error {
95
	if src == nil {
96
		*p = pguint64{Status: pgtype.Null}
97
		return nil
98
	}
99
100
	if len(src) != 4 {
101
		return fmt.Errorf("invalid length: %v", len(src))
102
	}
103
104
	n := binary.BigEndian.Uint64(src)
105
	*p = pguint64{Uint: n, Status: pgtype.Present}
106
	return nil
107
}
108
109
// EncodeText encodes to text format
110
func (p pguint64) EncodeText(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) {
111
	switch p.Status {
112
	case pgtype.Null:
113
		return nil, nil
114
	case pgtype.Undefined:
115
		return nil, errors.New("encode text status undefined status")
116
	}
117
118
	return append(buf, strconv.FormatUint(p.Uint, 10)...), nil
119
}
120
121
// EncodeBinary encodes to binary format
122
func (p pguint64) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) {
123
	switch p.Status {
124
	case pgtype.Null:
125
		return nil, nil
126
	case pgtype.Undefined:
127
		return nil, errors.New("encode text status undefined status")
128
	}
129
130
	return pgio.AppendUint64(buf, p.Uint), nil
131
}
132
133
// Scan implements the database/sql Scanner interface
134
func (p *pguint64) Scan(src interface{}) error {
135
	if src == nil {
136
		*p = pguint64{Status: pgtype.Null}
137
		return nil
138
	}
139
140
	switch src := src.(type) {
141
	case uint32:
142
		*p = pguint64{Uint: uint64(src), Status: pgtype.Present}
143
		return nil
144
	case int64:
145
		*p = pguint64{Uint: uint64(src), Status: pgtype.Present}
146
		return nil
147
	case uint64:
148
		*p = pguint64{Uint: src, Status: pgtype.Present}
149
		return nil
150
	case string:
151
		return p.DecodeText(nil, []byte(src))
152
	case []byte:
153
		srcCopy := make([]byte, len(src))
154
		copy(srcCopy, src)
155
		return p.DecodeText(nil, srcCopy)
156
	}
157
158
	return fmt.Errorf("cannot scan %T", src)
159
}
160
161
// Value implements the database/sql/driver Valuer interface
162
func (p pguint64) Value() (driver.Value, error) {
163
	switch p.Status {
164
	case pgtype.Present:
165
		return int64(p.Uint), nil
166
	case pgtype.Null:
167
		return nil, nil
168
	default:
169
		return nil, errors.New("encode text status undefined status")
170
	}
171
}
172