mirror of https://github.com/jackc/pgx.git
Add status to Int4 and Int8
parent
6fe76fcfc2
commit
984500455c
7
conn.go
7
conn.go
|
@ -279,15 +279,12 @@ func (c *Conn) connect(config ConnConfig, network, address string, tlsConfig *tl
|
||||||
c.doneChan = make(chan struct{})
|
c.doneChan = make(chan struct{})
|
||||||
c.closedChan = make(chan error)
|
c.closedChan = make(chan error)
|
||||||
|
|
||||||
i4 := pgtype.Int4(0)
|
|
||||||
i8 := pgtype.Int8(0)
|
|
||||||
|
|
||||||
c.oidPgtypeValues = map[OID]pgtype.Value{
|
c.oidPgtypeValues = map[OID]pgtype.Value{
|
||||||
BoolOID: &pgtype.Bool{},
|
BoolOID: &pgtype.Bool{},
|
||||||
DateOID: &pgtype.Date{},
|
DateOID: &pgtype.Date{},
|
||||||
Int2OID: &pgtype.Int2{},
|
Int2OID: &pgtype.Int2{},
|
||||||
Int4OID: &i4,
|
Int4OID: &pgtype.Int4{},
|
||||||
Int8OID: &i8,
|
Int8OID: &pgtype.Int8{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if tlsConfig != nil {
|
if tlsConfig != nil {
|
||||||
|
|
|
@ -9,27 +9,30 @@ import (
|
||||||
"github.com/jackc/pgx/pgio"
|
"github.com/jackc/pgx/pgio"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Int4 int32
|
type Int4 struct {
|
||||||
|
Int int32
|
||||||
|
Status Status
|
||||||
|
}
|
||||||
|
|
||||||
func (i *Int4) ConvertFrom(src interface{}) error {
|
func (i *Int4) ConvertFrom(src interface{}) error {
|
||||||
switch value := src.(type) {
|
switch value := src.(type) {
|
||||||
case Int4:
|
case Int4:
|
||||||
*i = value
|
*i = value
|
||||||
case int8:
|
case int8:
|
||||||
*i = Int4(value)
|
*i = Int4{Int: int32(value), Status: Present}
|
||||||
case uint8:
|
case uint8:
|
||||||
*i = Int4(value)
|
*i = Int4{Int: int32(value), Status: Present}
|
||||||
case int16:
|
case int16:
|
||||||
*i = Int4(value)
|
*i = Int4{Int: int32(value), Status: Present}
|
||||||
case uint16:
|
case uint16:
|
||||||
*i = Int4(value)
|
*i = Int4{Int: int32(value), Status: Present}
|
||||||
case int32:
|
case int32:
|
||||||
*i = Int4(value)
|
*i = Int4{Int: int32(value), Status: Present}
|
||||||
case uint32:
|
case uint32:
|
||||||
if value > math.MaxInt32 {
|
if value > math.MaxInt32 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
||||||
}
|
}
|
||||||
*i = Int4(value)
|
*i = Int4{Int: int32(value), Status: Present}
|
||||||
case int64:
|
case int64:
|
||||||
if value < math.MinInt32 {
|
if value < math.MinInt32 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
||||||
|
@ -37,12 +40,12 @@ func (i *Int4) ConvertFrom(src interface{}) error {
|
||||||
if value > math.MaxInt32 {
|
if value > math.MaxInt32 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
||||||
}
|
}
|
||||||
*i = Int4(value)
|
*i = Int4{Int: int32(value), Status: Present}
|
||||||
case uint64:
|
case uint64:
|
||||||
if value > math.MaxInt32 {
|
if value > math.MaxInt32 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
||||||
}
|
}
|
||||||
*i = Int4(value)
|
*i = Int4{Int: int32(value), Status: Present}
|
||||||
case int:
|
case int:
|
||||||
if value < math.MinInt32 {
|
if value < math.MinInt32 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
||||||
|
@ -50,18 +53,18 @@ func (i *Int4) ConvertFrom(src interface{}) error {
|
||||||
if value > math.MaxInt32 {
|
if value > math.MaxInt32 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
||||||
}
|
}
|
||||||
*i = Int4(value)
|
*i = Int4{Int: int32(value), Status: Present}
|
||||||
case uint:
|
case uint:
|
||||||
if value > math.MaxInt32 {
|
if value > math.MaxInt32 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
return fmt.Errorf("%d is greater than maximum value for Int4", value)
|
||||||
}
|
}
|
||||||
*i = Int4(value)
|
*i = Int4{Int: int32(value), Status: Present}
|
||||||
case string:
|
case string:
|
||||||
num, err := strconv.ParseInt(value, 10, 32)
|
num, err := strconv.ParseInt(value, 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*i = Int4(num)
|
*i = Int4{Int: int32(num), Status: Present}
|
||||||
default:
|
default:
|
||||||
if originalSrc, ok := underlyingIntType(src); ok {
|
if originalSrc, ok := underlyingIntType(src); ok {
|
||||||
return i.ConvertFrom(originalSrc)
|
return i.ConvertFrom(originalSrc)
|
||||||
|
@ -83,7 +86,8 @@ func (i *Int4) DecodeText(r io.Reader) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if size == -1 {
|
if size == -1 {
|
||||||
return fmt.Errorf("invalid length for int4: %v", size)
|
*i = Int4{Status: Null}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, int(size))
|
buf := make([]byte, int(size))
|
||||||
|
@ -97,7 +101,7 @@ func (i *Int4) DecodeText(r io.Reader) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
*i = Int4(n)
|
*i = Int4{Int: int32(n), Status: Present}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +111,11 @@ func (i *Int4) DecodeBinary(r io.Reader) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if size == -1 {
|
||||||
|
*i = Int4{Status: Null}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if size != 4 {
|
if size != 4 {
|
||||||
return fmt.Errorf("invalid length for int4: %v", size)
|
return fmt.Errorf("invalid length for int4: %v", size)
|
||||||
}
|
}
|
||||||
|
@ -116,12 +125,16 @@ func (i *Int4) DecodeBinary(r io.Reader) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
*i = Int4(n)
|
*i = Int4{Int: n, Status: Present}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Int4) EncodeText(w io.Writer) error {
|
func (i Int4) EncodeText(w io.Writer) error {
|
||||||
s := strconv.FormatInt(int64(i), 10)
|
if done, err := encodeNotPresent(w, i.Status); done {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s := strconv.FormatInt(int64(i.Int), 10)
|
||||||
_, err := pgio.WriteInt32(w, int32(len(s)))
|
_, err := pgio.WriteInt32(w, int32(len(s)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -131,11 +144,15 @@ func (i Int4) EncodeText(w io.Writer) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Int4) EncodeBinary(w io.Writer) error {
|
func (i Int4) EncodeBinary(w io.Writer) error {
|
||||||
|
if done, err := encodeNotPresent(w, i.Status); done {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
_, err := pgio.WriteInt32(w, 4)
|
_, err := pgio.WriteInt32(w, 4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = pgio.WriteInt32(w, int32(i))
|
_, err = pgio.WriteInt32(w, i.Int)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,89 +1,21 @@
|
||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx"
|
|
||||||
"github.com/jackc/pgx/pgio"
|
|
||||||
"github.com/jackc/pgx/pgtype"
|
"github.com/jackc/pgx/pgtype"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInt4Transcode(t *testing.T) {
|
func TestInt4Transcode(t *testing.T) {
|
||||||
conn := mustConnectPgx(t)
|
testSuccessfulTranscode(t, "int4", []interface{}{
|
||||||
defer mustClose(t, conn)
|
pgtype.Int4{Int: math.MinInt32, Status: pgtype.Present},
|
||||||
|
pgtype.Int4{Int: -1, Status: pgtype.Present},
|
||||||
ps, err := conn.Prepare("test", "select $1::int4")
|
pgtype.Int4{Int: 0, Status: pgtype.Present},
|
||||||
if err != nil {
|
pgtype.Int4{Int: 1, Status: pgtype.Present},
|
||||||
t.Fatal(err)
|
pgtype.Int4{Int: math.MaxInt32, Status: pgtype.Present},
|
||||||
}
|
pgtype.Int4{Int: 0, Status: pgtype.Null},
|
||||||
|
})
|
||||||
tests := []struct {
|
|
||||||
result pgtype.Int4
|
|
||||||
}{
|
|
||||||
{result: pgtype.Int4(math.MinInt32)},
|
|
||||||
{result: pgtype.Int4(-1)},
|
|
||||||
{result: pgtype.Int4(0)},
|
|
||||||
{result: pgtype.Int4(1)},
|
|
||||||
{result: pgtype.Int4(math.MaxInt32)},
|
|
||||||
}
|
|
||||||
|
|
||||||
ps.FieldDescriptions[0].FormatCode = pgx.TextFormatCode
|
|
||||||
for i, tt := range tests {
|
|
||||||
inputBuf := &bytes.Buffer{}
|
|
||||||
err = tt.result.EncodeText(inputBuf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("TextFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var s string
|
|
||||||
err := conn.QueryRow("test", string(inputBuf.Bytes()[4:])).Scan(&s)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("TextFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
outputBuf := &bytes.Buffer{}
|
|
||||||
pgio.WriteInt32(outputBuf, int32(len(s)))
|
|
||||||
outputBuf.WriteString(s)
|
|
||||||
var r pgtype.Int4
|
|
||||||
err = r.DecodeText(outputBuf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("TextFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r != tt.result {
|
|
||||||
t.Errorf("TextFormat %d: expected %v, got %v", i, tt.result, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ps.FieldDescriptions[0].FormatCode = pgx.BinaryFormatCode
|
|
||||||
for i, tt := range tests {
|
|
||||||
inputBuf := &bytes.Buffer{}
|
|
||||||
err = tt.result.EncodeBinary(inputBuf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("BinaryFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf []byte
|
|
||||||
err := conn.QueryRow("test", inputBuf.Bytes()[4:]).Scan(&buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("BinaryFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
outputBuf := &bytes.Buffer{}
|
|
||||||
pgio.WriteInt32(outputBuf, int32(len(buf)))
|
|
||||||
outputBuf.Write(buf)
|
|
||||||
var r pgtype.Int4
|
|
||||||
err = r.DecodeBinary(outputBuf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("BinaryFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r != tt.result {
|
|
||||||
t.Errorf("BinaryFormat %d: expected %v, got %v", i, tt.result, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInt4ConvertFrom(t *testing.T) {
|
func TestInt4ConvertFrom(t *testing.T) {
|
||||||
|
@ -93,20 +25,20 @@ func TestInt4ConvertFrom(t *testing.T) {
|
||||||
source interface{}
|
source interface{}
|
||||||
result pgtype.Int4
|
result pgtype.Int4
|
||||||
}{
|
}{
|
||||||
{source: int8(1), result: pgtype.Int4(1)},
|
{source: int8(1), result: pgtype.Int4{Int: 1, Status: pgtype.Present}},
|
||||||
{source: int16(1), result: pgtype.Int4(1)},
|
{source: int16(1), result: pgtype.Int4{Int: 1, Status: pgtype.Present}},
|
||||||
{source: int32(1), result: pgtype.Int4(1)},
|
{source: int32(1), result: pgtype.Int4{Int: 1, Status: pgtype.Present}},
|
||||||
{source: int64(1), result: pgtype.Int4(1)},
|
{source: int64(1), result: pgtype.Int4{Int: 1, Status: pgtype.Present}},
|
||||||
{source: int8(-1), result: pgtype.Int4(-1)},
|
{source: int8(-1), result: pgtype.Int4{Int: -1, Status: pgtype.Present}},
|
||||||
{source: int16(-1), result: pgtype.Int4(-1)},
|
{source: int16(-1), result: pgtype.Int4{Int: -1, Status: pgtype.Present}},
|
||||||
{source: int32(-1), result: pgtype.Int4(-1)},
|
{source: int32(-1), result: pgtype.Int4{Int: -1, Status: pgtype.Present}},
|
||||||
{source: int64(-1), result: pgtype.Int4(-1)},
|
{source: int64(-1), result: pgtype.Int4{Int: -1, Status: pgtype.Present}},
|
||||||
{source: uint8(1), result: pgtype.Int4(1)},
|
{source: uint8(1), result: pgtype.Int4{Int: 1, Status: pgtype.Present}},
|
||||||
{source: uint16(1), result: pgtype.Int4(1)},
|
{source: uint16(1), result: pgtype.Int4{Int: 1, Status: pgtype.Present}},
|
||||||
{source: uint32(1), result: pgtype.Int4(1)},
|
{source: uint32(1), result: pgtype.Int4{Int: 1, Status: pgtype.Present}},
|
||||||
{source: uint64(1), result: pgtype.Int4(1)},
|
{source: uint64(1), result: pgtype.Int4{Int: 1, Status: pgtype.Present}},
|
||||||
{source: "1", result: pgtype.Int4(1)},
|
{source: "1", result: pgtype.Int4{Int: 1, Status: pgtype.Present}},
|
||||||
{source: _int8(1), result: pgtype.Int4(1)},
|
{source: _int8(1), result: pgtype.Int4{Int: 1, Status: pgtype.Present}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range successfulTests {
|
for i, tt := range successfulTests {
|
||||||
|
|
|
@ -9,31 +9,34 @@ import (
|
||||||
"github.com/jackc/pgx/pgio"
|
"github.com/jackc/pgx/pgio"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Int8 int64
|
type Int8 struct {
|
||||||
|
Int int64
|
||||||
|
Status Status
|
||||||
|
}
|
||||||
|
|
||||||
func (i *Int8) ConvertFrom(src interface{}) error {
|
func (i *Int8) ConvertFrom(src interface{}) error {
|
||||||
switch value := src.(type) {
|
switch value := src.(type) {
|
||||||
case Int8:
|
case Int8:
|
||||||
*i = value
|
*i = value
|
||||||
case int8:
|
case int8:
|
||||||
*i = Int8(value)
|
*i = Int8{Int: int64(value), Status: Present}
|
||||||
case uint8:
|
case uint8:
|
||||||
*i = Int8(value)
|
*i = Int8{Int: int64(value), Status: Present}
|
||||||
case int16:
|
case int16:
|
||||||
*i = Int8(value)
|
*i = Int8{Int: int64(value), Status: Present}
|
||||||
case uint16:
|
case uint16:
|
||||||
*i = Int8(value)
|
*i = Int8{Int: int64(value), Status: Present}
|
||||||
case int32:
|
case int32:
|
||||||
*i = Int8(value)
|
*i = Int8{Int: int64(value), Status: Present}
|
||||||
case uint32:
|
case uint32:
|
||||||
*i = Int8(value)
|
*i = Int8{Int: int64(value), Status: Present}
|
||||||
case int64:
|
case int64:
|
||||||
*i = Int8(value)
|
*i = Int8{Int: int64(value), Status: Present}
|
||||||
case uint64:
|
case uint64:
|
||||||
if value > math.MaxInt64 {
|
if value > math.MaxInt64 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int8", value)
|
return fmt.Errorf("%d is greater than maximum value for Int8", value)
|
||||||
}
|
}
|
||||||
*i = Int8(value)
|
*i = Int8{Int: int64(value), Status: Present}
|
||||||
case int:
|
case int:
|
||||||
if int64(value) < math.MinInt64 {
|
if int64(value) < math.MinInt64 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int8", value)
|
return fmt.Errorf("%d is greater than maximum value for Int8", value)
|
||||||
|
@ -41,18 +44,18 @@ func (i *Int8) ConvertFrom(src interface{}) error {
|
||||||
if int64(value) > math.MaxInt64 {
|
if int64(value) > math.MaxInt64 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int8", value)
|
return fmt.Errorf("%d is greater than maximum value for Int8", value)
|
||||||
}
|
}
|
||||||
*i = Int8(value)
|
*i = Int8{Int: int64(value), Status: Present}
|
||||||
case uint:
|
case uint:
|
||||||
if uint64(value) > math.MaxInt64 {
|
if uint64(value) > math.MaxInt64 {
|
||||||
return fmt.Errorf("%d is greater than maximum value for Int8", value)
|
return fmt.Errorf("%d is greater than maximum value for Int8", value)
|
||||||
}
|
}
|
||||||
*i = Int8(value)
|
*i = Int8{Int: int64(value), Status: Present}
|
||||||
case string:
|
case string:
|
||||||
num, err := strconv.ParseInt(value, 10, 64)
|
num, err := strconv.ParseInt(value, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*i = Int8(num)
|
*i = Int8{Int: num, Status: Present}
|
||||||
default:
|
default:
|
||||||
if originalSrc, ok := underlyingIntType(src); ok {
|
if originalSrc, ok := underlyingIntType(src); ok {
|
||||||
return i.ConvertFrom(originalSrc)
|
return i.ConvertFrom(originalSrc)
|
||||||
|
@ -74,7 +77,8 @@ func (i *Int8) DecodeText(r io.Reader) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if size == -1 {
|
if size == -1 {
|
||||||
return fmt.Errorf("invalid length for int8: %v", size)
|
*i = Int8{Status: Null}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, int(size))
|
buf := make([]byte, int(size))
|
||||||
|
@ -88,7 +92,7 @@ func (i *Int8) DecodeText(r io.Reader) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
*i = Int8(n)
|
*i = Int8{Int: n, Status: Present}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +102,11 @@ func (i *Int8) DecodeBinary(r io.Reader) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if size == -1 {
|
||||||
|
*i = Int8{Status: Null}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if size != 8 {
|
if size != 8 {
|
||||||
return fmt.Errorf("invalid length for int8: %v", size)
|
return fmt.Errorf("invalid length for int8: %v", size)
|
||||||
}
|
}
|
||||||
|
@ -107,12 +116,16 @@ func (i *Int8) DecodeBinary(r io.Reader) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
*i = Int8(n)
|
*i = Int8{Int: n, Status: Present}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Int8) EncodeText(w io.Writer) error {
|
func (i Int8) EncodeText(w io.Writer) error {
|
||||||
s := strconv.FormatInt(int64(i), 10)
|
if done, err := encodeNotPresent(w, i.Status); done {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s := strconv.FormatInt(i.Int, 10)
|
||||||
_, err := pgio.WriteInt32(w, int32(len(s)))
|
_, err := pgio.WriteInt32(w, int32(len(s)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -122,11 +135,15 @@ func (i Int8) EncodeText(w io.Writer) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Int8) EncodeBinary(w io.Writer) error {
|
func (i Int8) EncodeBinary(w io.Writer) error {
|
||||||
|
if done, err := encodeNotPresent(w, i.Status); done {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
_, err := pgio.WriteInt32(w, 8)
|
_, err := pgio.WriteInt32(w, 8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = pgio.WriteInt64(w, int64(i))
|
_, err = pgio.WriteInt64(w, i.Int)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,89 +1,21 @@
|
||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx"
|
|
||||||
"github.com/jackc/pgx/pgio"
|
|
||||||
"github.com/jackc/pgx/pgtype"
|
"github.com/jackc/pgx/pgtype"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInt8Transcode(t *testing.T) {
|
func TestInt8Transcode(t *testing.T) {
|
||||||
conn := mustConnectPgx(t)
|
testSuccessfulTranscode(t, "int8", []interface{}{
|
||||||
defer mustClose(t, conn)
|
pgtype.Int8{Int: math.MinInt64, Status: pgtype.Present},
|
||||||
|
pgtype.Int8{Int: -1, Status: pgtype.Present},
|
||||||
ps, err := conn.Prepare("test", "select $1::int8")
|
pgtype.Int8{Int: 0, Status: pgtype.Present},
|
||||||
if err != nil {
|
pgtype.Int8{Int: 1, Status: pgtype.Present},
|
||||||
t.Fatal(err)
|
pgtype.Int8{Int: math.MaxInt64, Status: pgtype.Present},
|
||||||
}
|
pgtype.Int8{Int: 0, Status: pgtype.Null},
|
||||||
|
})
|
||||||
tests := []struct {
|
|
||||||
result pgtype.Int8
|
|
||||||
}{
|
|
||||||
{result: pgtype.Int8(math.MinInt64)},
|
|
||||||
{result: pgtype.Int8(-1)},
|
|
||||||
{result: pgtype.Int8(0)},
|
|
||||||
{result: pgtype.Int8(1)},
|
|
||||||
{result: pgtype.Int8(math.MaxInt64)},
|
|
||||||
}
|
|
||||||
|
|
||||||
ps.FieldDescriptions[0].FormatCode = pgx.TextFormatCode
|
|
||||||
for i, tt := range tests {
|
|
||||||
inputBuf := &bytes.Buffer{}
|
|
||||||
err = tt.result.EncodeText(inputBuf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("TextFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var s string
|
|
||||||
err := conn.QueryRow("test", string(inputBuf.Bytes()[4:])).Scan(&s)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("TextFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
outputBuf := &bytes.Buffer{}
|
|
||||||
pgio.WriteInt32(outputBuf, int32(len(s)))
|
|
||||||
outputBuf.WriteString(s)
|
|
||||||
var r pgtype.Int8
|
|
||||||
err = r.DecodeText(outputBuf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("TextFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r != tt.result {
|
|
||||||
t.Errorf("TextFormat %d: expected %v, got %v", i, tt.result, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ps.FieldDescriptions[0].FormatCode = pgx.BinaryFormatCode
|
|
||||||
for i, tt := range tests {
|
|
||||||
inputBuf := &bytes.Buffer{}
|
|
||||||
err = tt.result.EncodeBinary(inputBuf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("BinaryFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf []byte
|
|
||||||
err := conn.QueryRow("test", inputBuf.Bytes()[4:]).Scan(&buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("BinaryFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
outputBuf := &bytes.Buffer{}
|
|
||||||
pgio.WriteInt32(outputBuf, int32(len(buf)))
|
|
||||||
outputBuf.Write(buf)
|
|
||||||
var r pgtype.Int8
|
|
||||||
err = r.DecodeBinary(outputBuf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("BinaryFormat %d: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r != tt.result {
|
|
||||||
t.Errorf("BinaryFormat %d: expected %v, got %v", i, tt.result, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInt8ConvertFrom(t *testing.T) {
|
func TestInt8ConvertFrom(t *testing.T) {
|
||||||
|
@ -93,20 +25,20 @@ func TestInt8ConvertFrom(t *testing.T) {
|
||||||
source interface{}
|
source interface{}
|
||||||
result pgtype.Int8
|
result pgtype.Int8
|
||||||
}{
|
}{
|
||||||
{source: int8(1), result: pgtype.Int8(1)},
|
{source: int8(1), result: pgtype.Int8{Int: 1, Status: pgtype.Present}},
|
||||||
{source: int16(1), result: pgtype.Int8(1)},
|
{source: int16(1), result: pgtype.Int8{Int: 1, Status: pgtype.Present}},
|
||||||
{source: int32(1), result: pgtype.Int8(1)},
|
{source: int32(1), result: pgtype.Int8{Int: 1, Status: pgtype.Present}},
|
||||||
{source: int64(1), result: pgtype.Int8(1)},
|
{source: int64(1), result: pgtype.Int8{Int: 1, Status: pgtype.Present}},
|
||||||
{source: int8(-1), result: pgtype.Int8(-1)},
|
{source: int8(-1), result: pgtype.Int8{Int: -1, Status: pgtype.Present}},
|
||||||
{source: int16(-1), result: pgtype.Int8(-1)},
|
{source: int16(-1), result: pgtype.Int8{Int: -1, Status: pgtype.Present}},
|
||||||
{source: int32(-1), result: pgtype.Int8(-1)},
|
{source: int32(-1), result: pgtype.Int8{Int: -1, Status: pgtype.Present}},
|
||||||
{source: int64(-1), result: pgtype.Int8(-1)},
|
{source: int64(-1), result: pgtype.Int8{Int: -1, Status: pgtype.Present}},
|
||||||
{source: uint8(1), result: pgtype.Int8(1)},
|
{source: uint8(1), result: pgtype.Int8{Int: 1, Status: pgtype.Present}},
|
||||||
{source: uint16(1), result: pgtype.Int8(1)},
|
{source: uint16(1), result: pgtype.Int8{Int: 1, Status: pgtype.Present}},
|
||||||
{source: uint32(1), result: pgtype.Int8(1)},
|
{source: uint32(1), result: pgtype.Int8{Int: 1, Status: pgtype.Present}},
|
||||||
{source: uint64(1), result: pgtype.Int8(1)},
|
{source: uint64(1), result: pgtype.Int8{Int: 1, Status: pgtype.Present}},
|
||||||
{source: "1", result: pgtype.Int8(1)},
|
{source: "1", result: pgtype.Int8{Int: 1, Status: pgtype.Present}},
|
||||||
{source: _int8(1), result: pgtype.Int8(1)},
|
{source: _int8(1), result: pgtype.Int8{Int: 1, Status: pgtype.Present}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range successfulTests {
|
for i, tt := range successfulTests {
|
||||||
|
|
18
values.go
18
values.go
|
@ -542,7 +542,7 @@ func (n NullInt32) Encode(w *WriteBuf, oid OID) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return pgtype.Int4(n.Int32).EncodeBinary(w)
|
return pgtype.Int4{Int: n.Int32, Status: pgtype.Present}.EncodeBinary(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OID (Object Identifier Type) is, according to https://www.postgresql.org/docs/current/static/datatype-oid.html,
|
// OID (Object Identifier Type) is, according to https://www.postgresql.org/docs/current/static/datatype-oid.html,
|
||||||
|
@ -788,7 +788,7 @@ func (n NullInt64) Encode(w *WriteBuf, oid OID) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return pgtype.Int8(n.Int64).EncodeBinary(w)
|
return pgtype.Int8{Int: n.Int64, Status: pgtype.Present}.EncodeBinary(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NullBool represents an bool that may be null. NullBool implements the Scanner
|
// NullBool represents an bool that may be null. NullBool implements the Scanner
|
||||||
|
@ -1487,7 +1487,12 @@ func decodeInt8(vr *ValueReader) int64 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return int64(n)
|
if n.Status == pgtype.Null {
|
||||||
|
vr.Fatal(ProtocolError("Cannot decode null into int16"))
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return n.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeChar(vr *ValueReader) Char {
|
func decodeChar(vr *ValueReader) Char {
|
||||||
|
@ -1584,7 +1589,12 @@ func decodeInt4(vr *ValueReader) int32 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return int32(n)
|
if n.Status == pgtype.Null {
|
||||||
|
vr.Fatal(ProtocolError("Cannot decode null into int16"))
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return n.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeOID(vr *ValueReader) OID {
|
func decodeOID(vr *ValueReader) OID {
|
||||||
|
|
Loading…
Reference in New Issue