Add simple protocol suuport with (Query|Exec)Ex
This commit is contained in:
+15
-2
@@ -8,10 +8,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestCidTranscode(t *testing.T) {
|
func TestCidTranscode(t *testing.T) {
|
||||||
testSuccessfulTranscode(t, "cid", []interface{}{
|
pgTypeName := "cid"
|
||||||
|
values := []interface{}{
|
||||||
pgtype.Cid{Uint: 42, Status: pgtype.Present},
|
pgtype.Cid{Uint: 42, Status: pgtype.Present},
|
||||||
pgtype.Cid{Status: pgtype.Null},
|
pgtype.Cid{Status: pgtype.Null},
|
||||||
})
|
}
|
||||||
|
eqFunc := func(a, b interface{}) bool {
|
||||||
|
return reflect.DeepEqual(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
testPgxSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
|
||||||
|
|
||||||
|
// No direct conversion from int to cid, convert through text
|
||||||
|
testPgxSimpleProtocolSuccessfulTranscodeEqFunc(t, "text::"+pgTypeName, values, eqFunc)
|
||||||
|
|
||||||
|
for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
|
||||||
|
testDatabaseSQLSuccessfulTranscodeEqFunc(t, driverName, pgTypeName, values, eqFunc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCidSet(t *testing.T) {
|
func TestCidSet(t *testing.T) {
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ func (dst *Json) Scan(src interface{}) error {
|
|||||||
func (src Json) Value() (driver.Value, error) {
|
func (src Json) Value() (driver.Value, error) {
|
||||||
switch src.Status {
|
switch src.Status {
|
||||||
case Present:
|
case Present:
|
||||||
return src.Bytes, nil
|
return string(src.Bytes), nil
|
||||||
case Null:
|
case Null:
|
||||||
return nil, nil
|
return nil, nil
|
||||||
default:
|
default:
|
||||||
|
|||||||
+19
-2
@@ -121,13 +121,13 @@ func (src *Numeric) AssignTo(dst interface{}) error {
|
|||||||
case Present:
|
case Present:
|
||||||
switch v := dst.(type) {
|
switch v := dst.(type) {
|
||||||
case *float32:
|
case *float32:
|
||||||
f, err := strconv.ParseFloat(src.Int.String(), 64)
|
f, err := src.toFloat64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return float64AssignTo(f, src.Status, dst)
|
return float64AssignTo(f, src.Status, dst)
|
||||||
case *float64:
|
case *float64:
|
||||||
f, err := strconv.ParseFloat(src.Int.String(), 64)
|
f, err := src.toFloat64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -283,6 +283,23 @@ func (dst *Numeric) toBigInt() (*big.Int, error) {
|
|||||||
return num, nil
|
return num, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (src *Numeric) toFloat64() (float64, error) {
|
||||||
|
f, err := strconv.ParseFloat(src.Int.String(), 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if src.Exp > 0 {
|
||||||
|
for i := 0; i < int(src.Exp); i++ {
|
||||||
|
f *= 10
|
||||||
|
}
|
||||||
|
} else if src.Exp < 0 {
|
||||||
|
for i := 0; i > int(src.Exp); i-- {
|
||||||
|
f /= 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (dst *Numeric) DecodeText(ci *ConnInfo, src []byte) error {
|
func (dst *Numeric) DecodeText(ci *ConnInfo, src []byte) error {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
*dst = Numeric{Status: Null}
|
*dst = Numeric{Status: Null}
|
||||||
|
|||||||
@@ -247,9 +247,12 @@ func TestNumericAssignTo(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &f32, expected: float32(42)},
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &f32, expected: float32(42)},
|
||||||
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &f64, expected: float64(42)},
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &f64, expected: float64(42)},
|
||||||
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Exp: -1, Status: pgtype.Present}, dst: &f32, expected: float32(4.2)},
|
||||||
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Exp: -1, Status: pgtype.Present}, dst: &f64, expected: float64(4.2)},
|
||||||
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i16, expected: int16(42)},
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i16, expected: int16(42)},
|
||||||
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i32, expected: int32(42)},
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i32, expected: int32(42)},
|
||||||
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i64, expected: int64(42)},
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i64, expected: int64(42)},
|
||||||
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Exp: 3, Status: pgtype.Present}, dst: &i64, expected: int64(42000)},
|
||||||
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i, expected: int(42)},
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i, expected: int(42)},
|
||||||
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &ui8, expected: uint8(42)},
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &ui8, expected: uint8(42)},
|
||||||
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &ui16, expected: uint16(42)},
|
{src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &ui16, expected: uint16(42)},
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -125,6 +126,7 @@ func testSuccessfulTranscode(t testing.TB, pgTypeName string, values []interface
|
|||||||
|
|
||||||
func testSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
|
func testSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
|
||||||
testPgxSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
|
testPgxSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
|
||||||
|
testPgxSimpleProtocolSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
|
||||||
for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
|
for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
|
||||||
testDatabaseSQLSuccessfulTranscodeEqFunc(t, driverName, pgTypeName, values, eqFunc)
|
testDatabaseSQLSuccessfulTranscodeEqFunc(t, driverName, pgTypeName, values, eqFunc)
|
||||||
}
|
}
|
||||||
@@ -175,6 +177,35 @@ func testPgxSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testPgxSimpleProtocolSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
|
||||||
|
conn := mustConnectPgx(t)
|
||||||
|
defer mustClose(t, conn)
|
||||||
|
|
||||||
|
for i, v := range values {
|
||||||
|
// Derefence value if it is a pointer
|
||||||
|
derefV := v
|
||||||
|
refVal := reflect.ValueOf(v)
|
||||||
|
if refVal.Kind() == reflect.Ptr {
|
||||||
|
derefV = refVal.Elem().Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
result := reflect.New(reflect.TypeOf(derefV))
|
||||||
|
err := conn.QueryRowEx(
|
||||||
|
context.Background(),
|
||||||
|
fmt.Sprintf("select ($1)::%s", pgTypeName),
|
||||||
|
&pgx.QueryExOptions{SimpleProtocol: true},
|
||||||
|
v,
|
||||||
|
).Scan(result.Interface())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Simple protocol %d: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !eqFunc(result.Elem().Interface(), derefV) {
|
||||||
|
t.Errorf("Simple protocol %d: expected %v, got %v", i, derefV, result.Elem().Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testDatabaseSQLSuccessfulTranscodeEqFunc(t testing.TB, driverName, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
|
func testDatabaseSQLSuccessfulTranscodeEqFunc(t testing.TB, driverName, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
|
||||||
conn := mustConnectDatabaseSQL(t, driverName)
|
conn := mustConnectDatabaseSQL(t, driverName)
|
||||||
defer mustClose(t, conn)
|
defer mustClose(t, conn)
|
||||||
|
|||||||
+15
-2
@@ -8,10 +8,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestXidTranscode(t *testing.T) {
|
func TestXidTranscode(t *testing.T) {
|
||||||
testSuccessfulTranscode(t, "xid", []interface{}{
|
pgTypeName := "xid"
|
||||||
|
values := []interface{}{
|
||||||
pgtype.Xid{Uint: 42, Status: pgtype.Present},
|
pgtype.Xid{Uint: 42, Status: pgtype.Present},
|
||||||
pgtype.Xid{Status: pgtype.Null},
|
pgtype.Xid{Status: pgtype.Null},
|
||||||
})
|
}
|
||||||
|
eqFunc := func(a, b interface{}) bool {
|
||||||
|
return reflect.DeepEqual(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
testPgxSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
|
||||||
|
|
||||||
|
// No direct conversion from int to xid, convert through text
|
||||||
|
testPgxSimpleProtocolSuccessfulTranscodeEqFunc(t, "text::"+pgTypeName, values, eqFunc)
|
||||||
|
|
||||||
|
for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
|
||||||
|
testDatabaseSQLSuccessfulTranscodeEqFunc(t, driverName, pgTypeName, values, eqFunc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestXidSet(t *testing.T) {
|
func TestXidSet(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user