mirror of https://github.com/jackc/pgx.git
Add more Null* types
* NullFloat32 * NullFloat64 * NullInteger16 * NullInteger32scan-io
parent
24395d98df
commit
32a368a75b
158
values.go
158
values.go
|
@ -60,6 +60,164 @@ type BinaryEncoder interface {
|
||||||
EncodeBinary(w *WriteBuf) error
|
EncodeBinary(w *WriteBuf) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NullFloat32 represents an smallint that may be null.
|
||||||
|
// NullFloat32 implements the Scanner, TextEncoder, and BinaryEncoder interfaces
|
||||||
|
// so it may be used both as an argument to Query[Row] and a destination for
|
||||||
|
// Scan for prepared and unprepared queries.
|
||||||
|
//
|
||||||
|
// If Valid is false then the value is NULL.
|
||||||
|
type NullFloat32 struct {
|
||||||
|
Float32 float32
|
||||||
|
Valid bool // Valid is true if Float32 is not NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullFloat32) Scan(rows *Rows, fd *FieldDescription, size int32) error {
|
||||||
|
if size == -1 {
|
||||||
|
n.Float32, n.Valid = 0, false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
n.Valid = true
|
||||||
|
n.Float32 = decodeFloat4(rows, fd, size)
|
||||||
|
return rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullFloat32) EncodeText() (string, error) {
|
||||||
|
if n.Valid {
|
||||||
|
return strconv.FormatFloat(float64(n.Float32), 'f', -1, 32), nil
|
||||||
|
} else {
|
||||||
|
return "null", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullFloat32) EncodeBinary(w *WriteBuf) error {
|
||||||
|
if !n.Valid {
|
||||||
|
w.WriteInt32(-1)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodeFloat4(w, n.Float32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NullFloat64 represents an smallint that may be null.
|
||||||
|
// NullFloat64 implements the Scanner, TextEncoder, and BinaryEncoder interfaces
|
||||||
|
// so it may be used both as an argument to Query[Row] and a destination for
|
||||||
|
// Scan for prepared and unprepared queries.
|
||||||
|
//
|
||||||
|
// If Valid is false then the value is NULL.
|
||||||
|
type NullFloat64 struct {
|
||||||
|
Float64 float64
|
||||||
|
Valid bool // Valid is true if Float64 is not NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullFloat64) Scan(rows *Rows, fd *FieldDescription, size int32) error {
|
||||||
|
if size == -1 {
|
||||||
|
n.Float64, n.Valid = 0, false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
n.Valid = true
|
||||||
|
n.Float64 = decodeFloat8(rows, fd, size)
|
||||||
|
return rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullFloat64) EncodeText() (string, error) {
|
||||||
|
if n.Valid {
|
||||||
|
return strconv.FormatFloat(n.Float64, 'f', -1, 64), nil
|
||||||
|
} else {
|
||||||
|
return "null", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullFloat64) EncodeBinary(w *WriteBuf) error {
|
||||||
|
if !n.Valid {
|
||||||
|
w.WriteInt32(-1)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodeFloat8(w, n.Float64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NullInt16 represents an smallint that may be null.
|
||||||
|
// NullInt16 implements the Scanner, TextEncoder, and BinaryEncoder interfaces
|
||||||
|
// so it may be used both as an argument to Query[Row] and a destination for
|
||||||
|
// Scan for prepared and unprepared queries.
|
||||||
|
//
|
||||||
|
// If Valid is false then the value is NULL.
|
||||||
|
type NullInt16 struct {
|
||||||
|
Int16 int16
|
||||||
|
Valid bool // Valid is true if Int16 is not NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullInt16) Scan(rows *Rows, fd *FieldDescription, size int32) error {
|
||||||
|
if size == -1 {
|
||||||
|
n.Int16, n.Valid = 0, false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
n.Valid = true
|
||||||
|
n.Int16 = decodeInt2(rows, fd, size)
|
||||||
|
return rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullInt16) EncodeText() (string, error) {
|
||||||
|
if n.Valid {
|
||||||
|
return strconv.FormatInt(int64(n.Int16), 10), nil
|
||||||
|
} else {
|
||||||
|
return "null", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullInt16) EncodeBinary(w *WriteBuf) error {
|
||||||
|
if !n.Valid {
|
||||||
|
w.WriteInt32(-1)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodeInt2(w, n.Int16)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NullInt32 represents an integer that may be null.
|
||||||
|
// NullInt32 implements the Scanner, TextEncoder, and BinaryEncoder interfaces
|
||||||
|
// so it may be used both as an argument to Query[Row] and a destination for
|
||||||
|
// Scan for prepared and unprepared queries.
|
||||||
|
//
|
||||||
|
// If Valid is false then the value is NULL.
|
||||||
|
type NullInt32 struct {
|
||||||
|
Int32 int32
|
||||||
|
Valid bool // Valid is true if Int64 is not NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullInt32) Scan(rows *Rows, fd *FieldDescription, size int32) error {
|
||||||
|
if size == -1 {
|
||||||
|
n.Int32, n.Valid = 0, false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
n.Valid = true
|
||||||
|
n.Int32 = decodeInt4(rows, fd, size)
|
||||||
|
return rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullInt32) EncodeText() (string, error) {
|
||||||
|
if n.Valid {
|
||||||
|
return strconv.FormatInt(int64(n.Int32), 10), nil
|
||||||
|
} else {
|
||||||
|
return "null", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NullInt32) EncodeBinary(w *WriteBuf) error {
|
||||||
|
if !n.Valid {
|
||||||
|
w.WriteInt32(-1)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodeInt4(w, n.Int32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NullInt64 represents an bigint that may be null.
|
||||||
|
// NullInt64 implements the Scanner, TextEncoder, and BinaryEncoder interfaces
|
||||||
|
// so it may be used both as an argument to Query[Row] and a destination for
|
||||||
|
// Scan for prepared and unprepared queries.
|
||||||
|
//
|
||||||
|
// If Valid is false then the value is NULL.
|
||||||
type NullInt64 struct {
|
type NullInt64 struct {
|
||||||
Int64 int64
|
Int64 int64
|
||||||
Valid bool // Valid is true if Int64 is not NULL
|
Valid bool // Valid is true if Int64 is not NULL
|
||||||
|
|
|
@ -194,7 +194,11 @@ func TestNullX(t *testing.T) {
|
||||||
defer closeConn(t, conn)
|
defer closeConn(t, conn)
|
||||||
|
|
||||||
type allTypes struct {
|
type allTypes struct {
|
||||||
|
i16 pgx.NullInt16
|
||||||
|
i32 pgx.NullInt32
|
||||||
i64 pgx.NullInt64
|
i64 pgx.NullInt64
|
||||||
|
f32 pgx.NullFloat32
|
||||||
|
f64 pgx.NullFloat64
|
||||||
}
|
}
|
||||||
|
|
||||||
var actual, zero allTypes
|
var actual, zero allTypes
|
||||||
|
@ -205,8 +209,16 @@ func TestNullX(t *testing.T) {
|
||||||
scanArgs []interface{}
|
scanArgs []interface{}
|
||||||
expected allTypes
|
expected allTypes
|
||||||
}{
|
}{
|
||||||
|
{"select $1::int2", []interface{}{&pgx.NullInt16{Int16: 1, Valid: true}}, []interface{}{&actual.i16}, allTypes{i16: pgx.NullInt16{Int16: 1, Valid: true}}},
|
||||||
|
{"select $1::int2", []interface{}{&pgx.NullInt16{Int16: 1, Valid: false}}, []interface{}{&actual.i16}, allTypes{i16: pgx.NullInt16{Int16: 0, Valid: false}}},
|
||||||
|
{"select $1::int4", []interface{}{&pgx.NullInt32{Int32: 1, Valid: true}}, []interface{}{&actual.i32}, allTypes{i32: pgx.NullInt32{Int32: 1, Valid: true}}},
|
||||||
|
{"select $1::int4", []interface{}{&pgx.NullInt32{Int32: 1, Valid: false}}, []interface{}{&actual.i32}, allTypes{i32: pgx.NullInt32{Int32: 0, Valid: false}}},
|
||||||
{"select $1::int8", []interface{}{&pgx.NullInt64{Int64: 1, Valid: true}}, []interface{}{&actual.i64}, allTypes{i64: pgx.NullInt64{Int64: 1, Valid: true}}},
|
{"select $1::int8", []interface{}{&pgx.NullInt64{Int64: 1, Valid: true}}, []interface{}{&actual.i64}, allTypes{i64: pgx.NullInt64{Int64: 1, Valid: true}}},
|
||||||
{"select $1::int8", []interface{}{&pgx.NullInt64{Int64: 1, Valid: false}}, []interface{}{&actual.i64}, allTypes{i64: pgx.NullInt64{Int64: 0, Valid: false}}},
|
{"select $1::int8", []interface{}{&pgx.NullInt64{Int64: 1, Valid: false}}, []interface{}{&actual.i64}, allTypes{i64: pgx.NullInt64{Int64: 0, Valid: false}}},
|
||||||
|
{"select $1::float4", []interface{}{&pgx.NullFloat32{Float32: 1.23, Valid: true}}, []interface{}{&actual.f32}, allTypes{f32: pgx.NullFloat32{Float32: 1.23, Valid: true}}},
|
||||||
|
{"select $1::float4", []interface{}{&pgx.NullFloat32{Float32: 1.23, Valid: false}}, []interface{}{&actual.f32}, allTypes{f32: pgx.NullFloat32{Float32: 0, Valid: false}}},
|
||||||
|
{"select $1::float8", []interface{}{&pgx.NullFloat64{Float64: 1.23, Valid: true}}, []interface{}{&actual.f64}, allTypes{f64: pgx.NullFloat64{Float64: 1.23, Valid: true}}},
|
||||||
|
{"select $1::float8", []interface{}{&pgx.NullFloat64{Float64: 1.23, Valid: false}}, []interface{}{&actual.f64}, allTypes{f64: pgx.NullFloat64{Float64: 0, Valid: false}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
|
|
Loading…
Reference in New Issue