diff --git a/conn_test.go b/conn_test.go index c0c1da64..5d0c0e56 100644 --- a/conn_test.go +++ b/conn_test.go @@ -680,23 +680,69 @@ func TestConnInitConnInfo(t *testing.T) { ensureConnValid(t, conn) } -func TestRegisteredDomainType(t *testing.T) { +func TestUnregisteredTypeUsableAsStringArgumentAndBaseResult(t *testing.T) { conn := mustConnectString(t, os.Getenv("PGX_TEST_DATABASE")) defer closeConn(t, conn) + var n uint64 + err := conn.QueryRow(context.Background(), "select $1::uint64", "42").Scan(&n) + if err != nil { + t.Fatal(err) + } + + if n != 42 { + t.Fatalf("Expected n to be 42, but was %v", n) + } + + ensureConnValid(t, conn) +} + +func TestDomainType(t *testing.T) { + conn := mustConnectString(t, os.Getenv("PGX_TEST_DATABASE")) + defer closeConn(t, conn) + + var err error + var n uint64 + + // Domain type uint64 is a PostgreSQL domain of underlying type numeric. + + // Since it is not registered, pgx does not know how to encode Go uint64 argument. + err = conn.QueryRow(context.Background(), "select $1::uint64", uint64(24)).Scan(&n) + if err == nil { + t.Fatal("expected error encoding uint64 into unregistered domain") + } + + // A string can be used. But a string cannot be the result because the describe result from the PostgreSQL server gives + // the underlying type of numeric. + err = conn.QueryRow(context.Background(), "select $1::uint64", "42").Scan(&n) + if err != nil { + t.Fatal(err) + } + if n != 42 { + t.Fatalf("Expected n to be 42, but was %v", n) + } + var uint64OID pgtype.OID - err := conn.QueryRow(context.Background(), "select t.oid from pg_type t where t.typname='uint64';").Scan(&uint64OID) + err = conn.QueryRow(context.Background(), "select t.oid from pg_type t where t.typname='uint64';").Scan(&uint64OID) if err != nil { t.Fatalf("did not find uint64 OID, %v", err) } conn.ConnInfo.RegisterDataType(pgtype.DataType{Value: &pgtype.Numeric{}, Name: "uint64", OID: uint64OID}) - var n uint64 + // String is still an acceptable argument after registration + err = conn.QueryRow(context.Background(), "select $1::uint64", "7").Scan(&n) + if err != nil { + t.Fatal(err) + } + if n != 7 { + t.Fatalf("Expected n to be 7, but was %v", n) + } + + // But a uint64 is acceptable err = conn.QueryRow(context.Background(), "select $1::uint64", uint64(24)).Scan(&n) if err != nil { t.Fatal(err) } - if n != 24 { t.Fatalf("Expected n to be 24, but was %v", n) } diff --git a/pgtype/aclitem.go b/pgtype/aclitem.go index 4da962dd..a54955eb 100644 --- a/pgtype/aclitem.go +++ b/pgtype/aclitem.go @@ -65,6 +65,7 @@ func (src *ACLItem) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/aclitem_array.go b/pgtype/aclitem_array.go index d8bf3303..2671022b 100644 --- a/pgtype/aclitem_array.go +++ b/pgtype/aclitem_array.go @@ -79,6 +79,7 @@ func (src *ACLItemArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/bool.go b/pgtype/bool.go index 0574588d..22774970 100644 --- a/pgtype/bool.go +++ b/pgtype/bool.go @@ -59,6 +59,7 @@ func (src *Bool) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/bool_array.go b/pgtype/bool_array.go index 623937dc..1aefcd27 100644 --- a/pgtype/bool_array.go +++ b/pgtype/bool_array.go @@ -81,6 +81,7 @@ func (src *BoolArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/bpchar_array.go b/pgtype/bpchar_array.go index d1ee2419..dd4a8363 100644 --- a/pgtype/bpchar_array.go +++ b/pgtype/bpchar_array.go @@ -81,6 +81,7 @@ func (src *BPCharArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/bytea.go b/pgtype/bytea.go index 4506dc31..064f199a 100644 --- a/pgtype/bytea.go +++ b/pgtype/bytea.go @@ -59,6 +59,7 @@ func (src *Bytea) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/bytea_array.go b/pgtype/bytea_array.go index 68122961..fc07d103 100644 --- a/pgtype/bytea_array.go +++ b/pgtype/bytea_array.go @@ -81,6 +81,7 @@ func (src *ByteaArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/cidr_array.go b/pgtype/cidr_array.go index 338d4904..62b0ca65 100644 --- a/pgtype/cidr_array.go +++ b/pgtype/cidr_array.go @@ -110,6 +110,7 @@ func (src *CIDRArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/date.go b/pgtype/date.go index 85c698aa..3f8d188a 100644 --- a/pgtype/date.go +++ b/pgtype/date.go @@ -67,6 +67,7 @@ func (src *Date) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/date_array.go b/pgtype/date_array.go index d04666f1..6d6c0899 100644 --- a/pgtype/date_array.go +++ b/pgtype/date_array.go @@ -82,6 +82,7 @@ func (src *DateArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/enum_array.go b/pgtype/enum_array.go index 7168cb8a..5de2badf 100644 --- a/pgtype/enum_array.go +++ b/pgtype/enum_array.go @@ -79,6 +79,7 @@ func (src *EnumArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/ext/satori-uuid/uuid.go b/pgtype/ext/satori-uuid/uuid.go index 78a90035..baebc5ed 100644 --- a/pgtype/ext/satori-uuid/uuid.go +++ b/pgtype/ext/satori-uuid/uuid.go @@ -78,6 +78,7 @@ func (src *UUID) AssignTo(dst interface{}) error { if nextDst, retry := pgtype.GetAssignToDstType(v); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case pgtype.Null: return pgtype.NullAssignTo(dst) diff --git a/pgtype/ext/shopspring-numeric/decimal.go b/pgtype/ext/shopspring-numeric/decimal.go index 507a93dc..7c1cd770 100644 --- a/pgtype/ext/shopspring-numeric/decimal.go +++ b/pgtype/ext/shopspring-numeric/decimal.go @@ -205,6 +205,7 @@ func (src *Numeric) AssignTo(dst interface{}) error { if nextDst, retry := pgtype.GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case pgtype.Null: return pgtype.NullAssignTo(dst) diff --git a/pgtype/float4_array.go b/pgtype/float4_array.go index 4e07ba43..b14161e8 100644 --- a/pgtype/float4_array.go +++ b/pgtype/float4_array.go @@ -81,6 +81,7 @@ func (src *Float4Array) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/float8_array.go b/pgtype/float8_array.go index e4c340b2..60e87236 100644 --- a/pgtype/float8_array.go +++ b/pgtype/float8_array.go @@ -81,6 +81,7 @@ func (src *Float8Array) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/hstore.go b/pgtype/hstore.go index 754c5a3f..8a84fe2a 100644 --- a/pgtype/hstore.go +++ b/pgtype/hstore.go @@ -68,6 +68,7 @@ func (src *Hstore) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/hstore_array.go b/pgtype/hstore_array.go index 239c5d9c..19d07686 100644 --- a/pgtype/hstore_array.go +++ b/pgtype/hstore_array.go @@ -81,6 +81,7 @@ func (src *HstoreArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/inet.go b/pgtype/inet.go index d93e6347..dfdd8868 100644 --- a/pgtype/inet.go +++ b/pgtype/inet.go @@ -86,6 +86,7 @@ func (src *Inet) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/inet_array.go b/pgtype/inet_array.go index 7b4cf457..51ad7988 100644 --- a/pgtype/inet_array.go +++ b/pgtype/inet_array.go @@ -110,6 +110,7 @@ func (src *InetArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/int2_array.go b/pgtype/int2_array.go index 5b4c2e1a..e3b9f64b 100644 --- a/pgtype/int2_array.go +++ b/pgtype/int2_array.go @@ -109,6 +109,7 @@ func (src *Int2Array) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/int4_array.go b/pgtype/int4_array.go index 77ad8654..ad75c4b5 100644 --- a/pgtype/int4_array.go +++ b/pgtype/int4_array.go @@ -128,6 +128,7 @@ func (src *Int4Array) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/int8_array.go b/pgtype/int8_array.go index 03b169d2..ae8d8e0f 100644 --- a/pgtype/int8_array.go +++ b/pgtype/int8_array.go @@ -109,6 +109,7 @@ func (src *Int8Array) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/interval.go b/pgtype/interval.go index 75969904..9172e14a 100644 --- a/pgtype/interval.go +++ b/pgtype/interval.go @@ -69,6 +69,7 @@ func (src *Interval) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/macaddr.go b/pgtype/macaddr.go index 79004be4..6854400b 100644 --- a/pgtype/macaddr.go +++ b/pgtype/macaddr.go @@ -65,6 +65,7 @@ func (src *Macaddr) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/macaddr_array.go b/pgtype/macaddr_array.go index c6bc2450..2d0439e9 100644 --- a/pgtype/macaddr_array.go +++ b/pgtype/macaddr_array.go @@ -82,6 +82,7 @@ func (src *MacaddrArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/numeric.go b/pgtype/numeric.go index fb6e1a00..91aff123 100644 --- a/pgtype/numeric.go +++ b/pgtype/numeric.go @@ -250,6 +250,7 @@ func (src *Numeric) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/numeric_array.go b/pgtype/numeric_array.go index 0d26f3b5..ec892cc8 100644 --- a/pgtype/numeric_array.go +++ b/pgtype/numeric_array.go @@ -165,6 +165,7 @@ func (src *NumericArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/record.go b/pgtype/record.go index 64c6f13a..315deda5 100644 --- a/pgtype/record.go +++ b/pgtype/record.go @@ -62,6 +62,7 @@ func (src *Record) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/text.go b/pgtype/text.go index 919743fe..648bbd58 100644 --- a/pgtype/text.go +++ b/pgtype/text.go @@ -69,6 +69,7 @@ func (src *Text) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/text_array.go b/pgtype/text_array.go index 88171d6c..1556fec8 100644 --- a/pgtype/text_array.go +++ b/pgtype/text_array.go @@ -81,6 +81,7 @@ func (src *TextArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/timestamp.go b/pgtype/timestamp.go index f8a4070d..93383e35 100644 --- a/pgtype/timestamp.go +++ b/pgtype/timestamp.go @@ -71,6 +71,7 @@ func (src *Timestamp) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/timestamp_array.go b/pgtype/timestamp_array.go index 493088a2..1fd1eefe 100644 --- a/pgtype/timestamp_array.go +++ b/pgtype/timestamp_array.go @@ -82,6 +82,7 @@ func (src *TimestampArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/timestamptz.go b/pgtype/timestamptz.go index ca9b538d..c2c91c29 100644 --- a/pgtype/timestamptz.go +++ b/pgtype/timestamptz.go @@ -72,6 +72,7 @@ func (src *Timestamptz) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/timestamptz_array.go b/pgtype/timestamptz_array.go index 612e9904..b87238ae 100644 --- a/pgtype/timestamptz_array.go +++ b/pgtype/timestamptz_array.go @@ -82,6 +82,7 @@ func (src *TimestamptzArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/typed_array.go.erb b/pgtype/typed_array.go.erb index b33e7d99..3ee637aa 100644 --- a/pgtype/typed_array.go.erb +++ b/pgtype/typed_array.go.erb @@ -81,6 +81,7 @@ func (src *<%= pgtype_array_type %>) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/uuid_array.go b/pgtype/uuid_array.go index cddd62f1..fac838af 100644 --- a/pgtype/uuid_array.go +++ b/pgtype/uuid_array.go @@ -137,6 +137,7 @@ func (src *UUIDArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/pgtype/varchar_array.go b/pgtype/varchar_array.go index 7b9257b8..d2359d03 100644 --- a/pgtype/varchar_array.go +++ b/pgtype/varchar_array.go @@ -81,6 +81,7 @@ func (src *VarcharArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) diff --git a/query_test.go b/query_test.go index c1b89656..0e6a6070 100644 --- a/query_test.go +++ b/query_test.go @@ -889,7 +889,7 @@ func TestQueryRowErrors(t *testing.T) { }{ // {"select $1::badtype", []interface{}{"Jack"}, []interface{}{&actual.i16}, `type "badtype" does not exist`}, // {"SYNTAX ERROR", []interface{}{}, []interface{}{&actual.i16}, "SQLSTATE 42601"}, - {"select $1::text", []interface{}{"Jack"}, []interface{}{&actual.i16}, "cannot decode"}, + {"select $1::text", []interface{}{"Jack"}, []interface{}{&actual.i16}, "unable to assign"}, // {"select $1::point", []interface{}{int(705)}, []interface{}{&actual.s}, "cannot convert 705 to Point"}, }