diff --git a/values.go b/values.go index 51f81b3e..d4af61eb 100644 --- a/values.go +++ b/values.go @@ -286,6 +286,44 @@ func (n NullInt64) EncodeBinary(w *WriteBuf) error { return encodeInt8(w, n.Int64) } +// NullBool represents an bigint that may be null. +// NullBool 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 NullBool struct { + Bool bool + Valid bool // Valid is true if Bool is not NULL +} + +func (n *NullBool) Scan(rows *Rows, fd *FieldDescription, size int32) error { + if size == -1 { + n.Bool, n.Valid = false, false + return nil + } + n.Valid = true + n.Bool = decodeBool(rows, fd, size) + return rows.Err() +} + +func (n NullBool) EncodeText() (string, byte, error) { + if n.Valid { + return strconv.FormatBool(n.Bool), SafeText, nil + } else { + return "", NullText, nil + } +} + +func (n NullBool) EncodeBinary(w *WriteBuf) error { + if !n.Valid { + w.WriteInt32(-1) + return nil + } + + return encodeBool(w, n.Bool) +} + var literalPattern *regexp.Regexp = regexp.MustCompile(`\$\d+`) // QuoteString escapes and quotes a string making it safe for interpolation diff --git a/values_test.go b/values_test.go index ad0b2742..aa2151c1 100644 --- a/values_test.go +++ b/values_test.go @@ -200,6 +200,7 @@ func TestNullX(t *testing.T) { i64 pgx.NullInt64 f32 pgx.NullFloat32 f64 pgx.NullFloat64 + b pgx.NullBool } var actual, zero allTypes @@ -222,6 +223,8 @@ func TestNullX(t *testing.T) { {"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}}}, + {"select $1::bool", []interface{}{pgx.NullBool{Bool: true, Valid: true}}, []interface{}{&actual.b}, allTypes{b: pgx.NullBool{Bool: true, Valid: true}}}, + {"select $1::bool", []interface{}{pgx.NullBool{Bool: true, Valid: false}}, []interface{}{&actual.b}, allTypes{b: pgx.NullBool{Bool: false, Valid: false}}}, } for i, tt := range tests {