From ab885b375b90c76db7e4a980c1974c31595d13ce Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Sat, 24 Aug 2019 13:49:12 -0500 Subject: [PATCH] OID type should only be used for scanning and encoding values It was a mistake to use it in other contexts. This made interop difficult between pacakges that depended on pgtype such as pgx and packages that did not like pgconn and pgproto3. In particular this was awkward for prepared statements. Because pgx depends on pgtype and the tests for pgtype depend on pgx this change will require a couple back and forth commits to get the go.mod dependecies correct. --- go.mod | 7 ++++--- go.sum | 31 +++++++++++++++++++++++++++++++ hstore_array_test.go | 10 +++++----- pgtype.go | 16 ++++++++-------- pgtype_test.go | 2 +- record.go | 2 +- record_test.go | 5 ++--- testutil/testutil.go | 6 +++--- 8 files changed, 55 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 075b4ee9..b3221838 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,10 @@ require ( github.com/lib/pq v1.1.0 github.com/satori/go.uuid v1.2.0 github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 - github.com/stretchr/testify v1.3.0 - go.uber.org/atomic v1.3.2 // indirect + github.com/stretchr/testify v1.4.0 go.uber.org/multierr v1.1.0 // indirect - golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373 + golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect ) + +replace github.com/jackc/pgx/v4 => ../pgx diff --git a/go.sum b/go.sum index 919c31c3..162c454f 100644 --- a/go.sum +++ b/go.sum @@ -2,10 +2,15 @@ github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMe github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0 h1:DUwgMQuuPnS0rhMXenUtZpqZqrR/30NWY+qQvTpSvEs= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3 h1:ZFYpB74Kq8xE9gmfxCmXD6QxZ27ja+j3HwGFc+YurhQ= github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb h1:d6GP9szHvXVopAOAnZ7WhRnF3Xdxrylmm/9jnfmW4Ag= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -14,6 +19,8 @@ github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db h1:UpaKn/gYxzH6/zWyRQH1S260zvKqwJJ4h8+Kf09ooh0= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711 h1:vZp4bYotXUkFx7JUSm7U8KV/7Q0AOdrQxxBBj0ZmZsg= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96 h1:ylEAOd688Duev/fxTmGdupsbyZfxNMdngIG14DoBKTM= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= @@ -27,6 +34,9 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0 h1:/5u4a+KGJptBRqGzPvYQL9p0d/tPR4S31+Tnzj9lEO4= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -42,15 +52,36 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a h1:Igim7XhdOpBnWPuYJ70XcNpq8q3BCACtVgNfoJxOV7g= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373 h1:PPwnA7z1Pjf7XYaBP9GL1VAMZmcIWyFz7QCMSIIa3Bg= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/hstore_array_test.go b/hstore_array_test.go index 47835605..ea8f03b0 100644 --- a/hstore_array_test.go +++ b/hstore_array_test.go @@ -14,14 +14,14 @@ func TestHstoreArrayTranscode(t *testing.T) { conn := testutil.MustConnectPgx(t) defer testutil.MustCloseContext(t, conn) - var hstoreOID pgtype.OID + var hstoreOID uint32 err := conn.QueryRow(context.Background(), "select t.oid from pg_type t where t.typname='hstore';").Scan(&hstoreOID) if err != nil { t.Fatalf("did not find hstore OID, %v", err) } conn.ConnInfo.RegisterDataType(pgtype.DataType{Value: &pgtype.Hstore{}, Name: "hstore", OID: hstoreOID}) - var hstoreArrayOID pgtype.OID + var hstoreArrayOID uint32 err = conn.QueryRow(context.Background(), "select t.oid from pg_type t where t.typname='_hstore';").Scan(&hstoreArrayOID) if err != nil { t.Fatalf("did not find _hstore OID, %v", err) @@ -70,7 +70,7 @@ func TestHstoreArrayTranscode(t *testing.T) { Status: pgtype.Present, } - ps, err := conn.Prepare(context.Background(), "test", "select $1::hstore[]") + _, err = conn.Prepare(context.Background(), "test", "select $1::hstore[]") if err != nil { t.Fatal(err) } @@ -84,7 +84,7 @@ func TestHstoreArrayTranscode(t *testing.T) { } for _, fc := range formats { - ps.FieldDescriptions[0].FormatCode = fc.formatCode + queryResultFormats := pgx.QueryResultFormats{fc.formatCode} vEncoder := testutil.ForceEncoder(src, fc.formatCode) if vEncoder == nil { t.Logf("%#v does not implement %v", src, fc.name) @@ -92,7 +92,7 @@ func TestHstoreArrayTranscode(t *testing.T) { } var result pgtype.HstoreArray - err := conn.QueryRow(context.Background(), "test", vEncoder).Scan(&result) + err := conn.QueryRow(context.Background(), "test", queryResultFormats, vEncoder).Scan(&result) if err != nil { t.Errorf("%v: %v", fc.name, err) continue diff --git a/pgtype.go b/pgtype.go index 94e8bcbc..6e187ae4 100644 --- a/pgtype.go +++ b/pgtype.go @@ -163,18 +163,18 @@ var errBadStatus = errors.New("invalid status") type DataType struct { Value Value Name string - OID OID + OID uint32 } type ConnInfo struct { - oidToDataType map[OID]*DataType + oidToDataType map[uint32]*DataType nameToDataType map[string]*DataType reflectTypeToDataType map[reflect.Type]*DataType } func NewConnInfo() *ConnInfo { ci := &ConnInfo{ - oidToDataType: make(map[OID]*DataType, 128), + oidToDataType: make(map[uint32]*DataType, 128), nameToDataType: make(map[string]*DataType, 128), reflectTypeToDataType: make(map[reflect.Type]*DataType, 128), } @@ -246,7 +246,7 @@ func NewConnInfo() *ConnInfo { return ci } -func (ci *ConnInfo) InitializeDataTypes(nameOIDs map[string]OID) { +func (ci *ConnInfo) InitializeDataTypes(nameOIDs map[string]uint32) { for name, oid := range nameOIDs { var value Value if t, ok := nameValues[name]; ok { @@ -264,7 +264,7 @@ func (ci *ConnInfo) RegisterDataType(t DataType) { ci.reflectTypeToDataType[reflect.ValueOf(t.Value).Type()] = &t } -func (ci *ConnInfo) DataTypeForOID(oid OID) (*DataType, bool) { +func (ci *ConnInfo) DataTypeForOID(oid uint32) (*DataType, bool) { dt, ok := ci.oidToDataType[oid] return dt, ok } @@ -282,7 +282,7 @@ func (ci *ConnInfo) DataTypeForValue(v Value) (*DataType, bool) { // DeepCopy makes a deep copy of the ConnInfo. func (ci *ConnInfo) DeepCopy() *ConnInfo { ci2 := &ConnInfo{ - oidToDataType: make(map[OID]*DataType, len(ci.oidToDataType)), + oidToDataType: make(map[uint32]*DataType, len(ci.oidToDataType)), nameToDataType: make(map[string]*DataType, len(ci.nameToDataType)), reflectTypeToDataType: make(map[reflect.Type]*DataType, len(ci.reflectTypeToDataType)), } @@ -298,7 +298,7 @@ func (ci *ConnInfo) DeepCopy() *ConnInfo { return ci2 } -func (ci *ConnInfo) Scan(oid OID, formatCode int16, buf []byte, dest interface{}) error { +func (ci *ConnInfo) Scan(oid uint32, formatCode int16, buf []byte, dest interface{}) error { if dest, ok := dest.(BinaryDecoder); ok && formatCode == BinaryFormatCode { return dest.DecodeBinary(ci, buf) } @@ -346,7 +346,7 @@ func (ci *ConnInfo) Scan(oid OID, formatCode int16, buf []byte, dest interface{} return scanUnknownType(oid, formatCode, buf, dest) } -func scanUnknownType(oid OID, formatCode int16, buf []byte, dest interface{}) error { +func scanUnknownType(oid uint32, formatCode int16, buf []byte, dest interface{}) error { switch dest := dest.(type) { case *string: if formatCode == BinaryFormatCode { diff --git a/pgtype_test.go b/pgtype_test.go index 53580d18..8771b77f 100644 --- a/pgtype_test.go +++ b/pgtype_test.go @@ -42,7 +42,7 @@ func mustParseMacaddr(t testing.TB, s string) net.HardwareAddr { } func TestConnInfoScanUnknownOID(t *testing.T) { - unknownOID := pgtype.OID(999999) + unknownOID := uint32(999999) srcBuf := []byte("foo") ci := pgtype.NewConnInfo() diff --git a/record.go b/record.go index 60733016..28f4a182 100644 --- a/record.go +++ b/record.go @@ -91,7 +91,7 @@ func (dst *Record) DecodeBinary(ci *ConnInfo, src []byte) error { if len(src[rp:]) < 8 { return errors.Errorf("Record incomplete %v", src) } - fieldOID := OID(binary.BigEndian.Uint32(src[rp:])) + fieldOID := binary.BigEndian.Uint32(src[rp:]) rp += 4 fieldLen := int(int32(binary.BigEndian.Uint32(src[rp:]))) diff --git a/record_test.go b/record_test.go index fbf36f5c..71a2f702 100644 --- a/record_test.go +++ b/record_test.go @@ -85,14 +85,13 @@ func TestRecordTranscode(t *testing.T) { for i, tt := range tests { psName := fmt.Sprintf("test%d", i) - ps, err := conn.Prepare(context.Background(), psName, tt.sql) + _, err := conn.Prepare(context.Background(), psName, tt.sql) if err != nil { t.Fatal(err) } - ps.FieldDescriptions[0].FormatCode = pgx.BinaryFormatCode var result pgtype.Record - if err := conn.QueryRow(context.Background(), psName).Scan(&result); err != nil { + if err := conn.QueryRow(context.Background(), psName, pgx.QueryResultFormats{pgx.BinaryFormatCode}).Scan(&result); err != nil { t.Errorf("%d: %v", i, err) continue } diff --git a/testutil/testutil.go b/testutil/testutil.go index 66deff39..068b7c59 100644 --- a/testutil/testutil.go +++ b/testutil/testutil.go @@ -225,12 +225,12 @@ func TestPgxSuccessfulNormalizeEqFunc(t testing.TB, tests []NormalizeTest, eqFun for i, tt := range tests { for _, fc := range formats { psName := fmt.Sprintf("test%d", i) - ps, err := conn.Prepare(context.Background(), psName, tt.SQL) + _, err := conn.Prepare(context.Background(), psName, tt.SQL) if err != nil { t.Fatal(err) } - ps.FieldDescriptions[0].FormatCode = fc.formatCode + queryResultFormats := pgx.QueryResultFormats{fc.formatCode} if ForceEncoder(tt.Value, fc.formatCode) == nil { t.Logf("Skipping: %#v does not implement %v", tt.Value, fc.name) continue @@ -243,7 +243,7 @@ func TestPgxSuccessfulNormalizeEqFunc(t testing.TB, tests []NormalizeTest, eqFun } result := reflect.New(reflect.TypeOf(derefV)) - err = conn.QueryRow(context.Background(), psName).Scan(result.Interface()) + err = conn.QueryRow(context.Background(), psName, queryResultFormats).Scan(result.Interface()) if err != nil { t.Errorf("%v %d: %v", fc.name, i, err) }