From 932caef6000e8c3cd5077a5d4777955b22d2353d Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Sat, 29 Apr 2017 12:23:51 -0500 Subject: [PATCH] pgtype DecodeText and DecodeBinary do not copy They now take ownership of the src argument. Needed to change Scan to make a copy of []byte arguments as lib/pq apparently gives Scan a shared memory buffer. --- pgtype/aclitem.go | 4 +++- pgtype/aclitem_array.go | 4 +++- pgtype/bool.go | 4 +++- pgtype/bool_array.go | 4 +++- pgtype/box.go | 4 +++- pgtype/bytea.go | 5 +---- pgtype/bytea_array.go | 4 +++- pgtype/cidr_array.go | 4 +++- pgtype/circle.go | 4 +++- pgtype/date.go | 4 +++- pgtype/date_array.go | 4 +++- pgtype/daterange.go | 10 ++++++---- pgtype/float4.go | 4 +++- pgtype/float4_array.go | 4 +++- pgtype/float8.go | 4 +++- pgtype/float8_array.go | 4 +++- pgtype/hstore.go | 4 +++- pgtype/hstore_array.go | 4 +++- pgtype/inet.go | 4 +++- pgtype/inet_array.go | 4 +++- pgtype/int2.go | 4 +++- pgtype/int2_array.go | 4 +++- pgtype/int4.go | 4 +++- pgtype/int4_array.go | 4 +++- pgtype/int4range.go | 10 ++++++---- pgtype/int8.go | 4 +++- pgtype/int8_array.go | 4 +++- pgtype/int8range.go | 10 ++++++---- pgtype/interval.go | 4 +++- pgtype/json.go | 9 ++++----- pgtype/jsonb.go | 6 +----- pgtype/line.go | 4 +++- pgtype/lseg.go | 4 +++- pgtype/macaddr.go | 4 +++- pgtype/numeric.go | 4 +++- pgtype/numeric_array.go | 4 +++- pgtype/numrange.go | 10 ++++++---- pgtype/oid.go | 4 +++- pgtype/path.go | 4 +++- pgtype/pgtype.go | 8 ++++---- pgtype/pguint32.go | 4 +++- pgtype/point.go | 4 +++- pgtype/polygon.go | 4 +++- pgtype/text.go | 4 +++- pgtype/text_array.go | 4 +++- pgtype/tid.go | 4 +++- pgtype/timestamp.go | 4 +++- pgtype/timestamp_array.go | 4 +++- pgtype/timestamptz.go | 4 +++- pgtype/timestamptz_array.go | 4 +++- pgtype/tsrange.go | 10 ++++++---- pgtype/tstzrange.go | 10 ++++++---- pgtype/typed_array.go.erb | 4 +++- pgtype/typed_range.go.erb | 4 +++- pgtype/uuid.go | 4 +++- pgtype/varbit.go | 9 ++++----- pgtype/varchar_array.go | 4 +++- 57 files changed, 188 insertions(+), 93 deletions(-) diff --git a/pgtype/aclitem.go b/pgtype/aclitem.go index ebfcc3e7..31065764 100644 --- a/pgtype/aclitem.go +++ b/pgtype/aclitem.go @@ -106,7 +106,9 @@ func (dst *Aclitem) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/aclitem_array.go b/pgtype/aclitem_array.go index 7ef76573..480b5bba 100644 --- a/pgtype/aclitem_array.go +++ b/pgtype/aclitem_array.go @@ -206,7 +206,9 @@ func (dst *AclitemArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/bool.go b/pgtype/bool.go index 9d309f0c..ba876c91 100644 --- a/pgtype/bool.go +++ b/pgtype/bool.go @@ -142,7 +142,9 @@ func (dst *Bool) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/bool_array.go b/pgtype/bool_array.go index 468f6816..4e92a616 100644 --- a/pgtype/bool_array.go +++ b/pgtype/bool_array.go @@ -308,7 +308,9 @@ func (dst *BoolArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/box.go b/pgtype/box.go index 2e4f39ee..e25af854 100644 --- a/pgtype/box.go +++ b/pgtype/box.go @@ -156,7 +156,9 @@ func (dst *Box) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/bytea.go b/pgtype/bytea.go index 3e2661db..bf774476 100644 --- a/pgtype/bytea.go +++ b/pgtype/bytea.go @@ -95,10 +95,7 @@ func (dst *Bytea) DecodeBinary(ci *ConnInfo, src []byte) error { return nil } - buf := make([]byte, len(src)) - copy(buf, src) - - *dst = Bytea{Bytes: buf, Status: Present} + *dst = Bytea{Bytes: src, Status: Present} return nil } diff --git a/pgtype/bytea_array.go b/pgtype/bytea_array.go index 4aa2b862..dd79b991 100644 --- a/pgtype/bytea_array.go +++ b/pgtype/bytea_array.go @@ -308,7 +308,9 @@ func (dst *ByteaArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/cidr_array.go b/pgtype/cidr_array.go index 96d912ae..0aa289e7 100644 --- a/pgtype/cidr_array.go +++ b/pgtype/cidr_array.go @@ -337,7 +337,9 @@ func (dst *CidrArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/circle.go b/pgtype/circle.go index 8c8f4693..e9268a06 100644 --- a/pgtype/circle.go +++ b/pgtype/circle.go @@ -138,7 +138,9 @@ func (dst *Circle) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/date.go b/pgtype/date.go index 993a04c5..a7e4762a 100644 --- a/pgtype/date.go +++ b/pgtype/date.go @@ -185,7 +185,9 @@ func (dst *Date) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) case time.Time: *dst = Date{Time: src, Status: Present} return nil diff --git a/pgtype/date_array.go b/pgtype/date_array.go index f24bf6b9..91e2ee62 100644 --- a/pgtype/date_array.go +++ b/pgtype/date_array.go @@ -309,7 +309,9 @@ func (dst *DateArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/daterange.go b/pgtype/daterange.go index 5cecca20..a5cd5d95 100644 --- a/pgtype/daterange.go +++ b/pgtype/daterange.go @@ -106,7 +106,7 @@ func (dst *Daterange) DecodeBinary(ci *ConnInfo, src []byte) error { return nil } -func (src *Daterange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Daterange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -166,7 +166,7 @@ func (src *Daterange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { return false, nil } -func (src *Daterange) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Daterange) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -256,13 +256,15 @@ func (dst *Daterange) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) } // Value implements the database/sql/driver Valuer interface. -func (src *Daterange) Value() (driver.Value, error) { +func (src Daterange) Value() (driver.Value, error) { return EncodeValueText(src) } diff --git a/pgtype/float4.go b/pgtype/float4.go index 76be4203..77bc4878 100644 --- a/pgtype/float4.go +++ b/pgtype/float4.go @@ -177,7 +177,9 @@ func (dst *Float4) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/float4_array.go b/pgtype/float4_array.go index db1523f0..38508a52 100644 --- a/pgtype/float4_array.go +++ b/pgtype/float4_array.go @@ -308,7 +308,9 @@ func (dst *Float4Array) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/float8.go b/pgtype/float8.go index 8cfc53c5..5322e251 100644 --- a/pgtype/float8.go +++ b/pgtype/float8.go @@ -167,7 +167,9 @@ func (dst *Float8) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/float8_array.go b/pgtype/float8_array.go index 19878bbb..2f310bbd 100644 --- a/pgtype/float8_array.go +++ b/pgtype/float8_array.go @@ -308,7 +308,9 @@ func (dst *Float8Array) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/hstore.go b/pgtype/hstore.go index 04df2acc..69a35b17 100644 --- a/pgtype/hstore.go +++ b/pgtype/hstore.go @@ -455,7 +455,9 @@ func (dst *Hstore) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/hstore_array.go b/pgtype/hstore_array.go index e4263f20..9f773af2 100644 --- a/pgtype/hstore_array.go +++ b/pgtype/hstore_array.go @@ -308,7 +308,9 @@ func (dst *HstoreArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/inet.go b/pgtype/inet.go index e3a7ec88..7c09a549 100644 --- a/pgtype/inet.go +++ b/pgtype/inet.go @@ -213,7 +213,9 @@ func (dst *Inet) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/inet_array.go b/pgtype/inet_array.go index 4687b145..ed9f5d1c 100644 --- a/pgtype/inet_array.go +++ b/pgtype/inet_array.go @@ -337,7 +337,9 @@ func (dst *InetArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/int2.go b/pgtype/int2.go index 4a3beb22..028cdfcf 100644 --- a/pgtype/int2.go +++ b/pgtype/int2.go @@ -178,7 +178,9 @@ func (dst *Int2) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/int2_array.go b/pgtype/int2_array.go index 3506370e..cdfcde48 100644 --- a/pgtype/int2_array.go +++ b/pgtype/int2_array.go @@ -336,7 +336,9 @@ func (dst *Int2Array) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/int4.go b/pgtype/int4.go index f429d887..cae0d32a 100644 --- a/pgtype/int4.go +++ b/pgtype/int4.go @@ -169,7 +169,9 @@ func (dst *Int4) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/int4_array.go b/pgtype/int4_array.go index e4ec6455..9ca0b067 100644 --- a/pgtype/int4_array.go +++ b/pgtype/int4_array.go @@ -336,7 +336,9 @@ func (dst *Int4Array) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/int4range.go b/pgtype/int4range.go index 12a48dab..29b8371e 100644 --- a/pgtype/int4range.go +++ b/pgtype/int4range.go @@ -106,7 +106,7 @@ func (dst *Int4range) DecodeBinary(ci *ConnInfo, src []byte) error { return nil } -func (src *Int4range) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Int4range) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -166,7 +166,7 @@ func (src *Int4range) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { return false, nil } -func (src *Int4range) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Int4range) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -256,13 +256,15 @@ func (dst *Int4range) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) } // Value implements the database/sql/driver Valuer interface. -func (src *Int4range) Value() (driver.Value, error) { +func (src Int4range) Value() (driver.Value, error) { return EncodeValueText(src) } diff --git a/pgtype/int8.go b/pgtype/int8.go index 97db8393..a4ec4e62 100644 --- a/pgtype/int8.go +++ b/pgtype/int8.go @@ -155,7 +155,9 @@ func (dst *Int8) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/int8_array.go b/pgtype/int8_array.go index 6c0dab65..c5026f83 100644 --- a/pgtype/int8_array.go +++ b/pgtype/int8_array.go @@ -336,7 +336,9 @@ func (dst *Int8Array) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/int8range.go b/pgtype/int8range.go index 3541dbe2..e3e0486f 100644 --- a/pgtype/int8range.go +++ b/pgtype/int8range.go @@ -106,7 +106,7 @@ func (dst *Int8range) DecodeBinary(ci *ConnInfo, src []byte) error { return nil } -func (src *Int8range) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Int8range) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -166,7 +166,7 @@ func (src *Int8range) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { return false, nil } -func (src *Int8range) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Int8range) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -256,13 +256,15 @@ func (dst *Int8range) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) } // Value implements the database/sql/driver Valuer interface. -func (src *Int8range) Value() (driver.Value, error) { +func (src Int8range) Value() (driver.Value, error) { return EncodeValueText(src) } diff --git a/pgtype/interval.go b/pgtype/interval.go index 050d5610..8ce345a3 100644 --- a/pgtype/interval.go +++ b/pgtype/interval.go @@ -259,7 +259,9 @@ func (dst *Interval) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/json.go b/pgtype/json.go index a027a91c..44880863 100644 --- a/pgtype/json.go +++ b/pgtype/json.go @@ -97,10 +97,7 @@ func (dst *Json) DecodeText(ci *ConnInfo, src []byte) error { return nil } - buf := make([]byte, len(src)) - copy(buf, src) - - *dst = Json{Bytes: buf, Status: Present} + *dst = Json{Bytes: src, Status: Present} return nil } @@ -135,7 +132,9 @@ func (dst *Json) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/jsonb.go b/pgtype/jsonb.go index 82cbb21f..5533b4b4 100644 --- a/pgtype/jsonb.go +++ b/pgtype/jsonb.go @@ -37,12 +37,8 @@ func (dst *Jsonb) DecodeBinary(ci *ConnInfo, src []byte) error { if src[0] != 1 { return fmt.Errorf("unknown jsonb version number %d", src[0]) } - src = src[1:] - buf := make([]byte, len(src)) - copy(buf, src) - - *dst = Jsonb{Bytes: buf, Status: Present} + *dst = Jsonb{Bytes: src[1:], Status: Present} return nil } diff --git a/pgtype/line.go b/pgtype/line.go index 06f01f21..75fdf207 100644 --- a/pgtype/line.go +++ b/pgtype/line.go @@ -136,7 +136,9 @@ func (dst *Line) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/lseg.go b/pgtype/lseg.go index 986724cc..823c2c09 100644 --- a/pgtype/lseg.go +++ b/pgtype/lseg.go @@ -156,7 +156,9 @@ func (dst *Lseg) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/macaddr.go b/pgtype/macaddr.go index 0fe092e4..785148a2 100644 --- a/pgtype/macaddr.go +++ b/pgtype/macaddr.go @@ -142,7 +142,9 @@ func (dst *Macaddr) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/numeric.go b/pgtype/numeric.go index 63f99c06..8dbc0251 100644 --- a/pgtype/numeric.go +++ b/pgtype/numeric.go @@ -594,7 +594,9 @@ func (dst *Numeric) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/numeric_array.go b/pgtype/numeric_array.go index 3d59a6b0..2fc844eb 100644 --- a/pgtype/numeric_array.go +++ b/pgtype/numeric_array.go @@ -336,7 +336,9 @@ func (dst *NumericArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/numrange.go b/pgtype/numrange.go index b0baec9a..bac6fc4b 100644 --- a/pgtype/numrange.go +++ b/pgtype/numrange.go @@ -106,7 +106,7 @@ func (dst *Numrange) DecodeBinary(ci *ConnInfo, src []byte) error { return nil } -func (src *Numrange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Numrange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -166,7 +166,7 @@ func (src *Numrange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { return false, nil } -func (src *Numrange) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Numrange) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -256,13 +256,15 @@ func (dst *Numrange) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) } // Value implements the database/sql/driver Valuer interface. -func (src *Numrange) Value() (driver.Value, error) { +func (src Numrange) Value() (driver.Value, error) { return EncodeValueText(src) } diff --git a/pgtype/oid.go b/pgtype/oid.go index 339dee0f..58a7b0f5 100644 --- a/pgtype/oid.go +++ b/pgtype/oid.go @@ -70,7 +70,9 @@ func (dst *Oid) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/path.go b/pgtype/path.go index 2fd6cfc7..c1aa76bc 100644 --- a/pgtype/path.go +++ b/pgtype/path.go @@ -195,7 +195,9 @@ func (dst *Path) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/pgtype.go b/pgtype/pgtype.go index 27a1a091..3a6b7471 100644 --- a/pgtype/pgtype.go +++ b/pgtype/pgtype.go @@ -96,15 +96,15 @@ type Value interface { type BinaryDecoder interface { // DecodeBinary decodes src into BinaryDecoder. If src is nil then the - // original SQL value is NULL. BinaryDecoder MUST not retain a reference to - // src. It MUST make a copy if it needs to retain the raw bytes. + // original SQL value is NULL. BinaryDecoder takes ownership of src. The + // caller MUST not use it again. DecodeBinary(ci *ConnInfo, src []byte) error } type TextDecoder interface { // DecodeText decodes src into TextDecoder. If src is nil then the original - // SQL value is NULL. TextDecoder MUST not retain a reference to src. It MUST - // make a copy if it needs to retain the raw bytes. + // SQL value is NULL. TextDecoder takes ownership of src. The caller MUST not + // use it again. DecodeText(ci *ConnInfo, src []byte) error } diff --git a/pgtype/pguint32.go b/pgtype/pguint32.go index 0caa0cba..a13c1fcd 100644 --- a/pgtype/pguint32.go +++ b/pgtype/pguint32.go @@ -144,7 +144,9 @@ func (dst *pguint32) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/point.go b/pgtype/point.go index 3d51766e..62901340 100644 --- a/pgtype/point.go +++ b/pgtype/point.go @@ -130,7 +130,9 @@ func (dst *Point) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/polygon.go b/pgtype/polygon.go index af99ee3d..c4383765 100644 --- a/pgtype/polygon.go +++ b/pgtype/polygon.go @@ -174,7 +174,9 @@ func (dst *Polygon) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/text.go b/pgtype/text.go index 8e42a756..54e2d774 100644 --- a/pgtype/text.go +++ b/pgtype/text.go @@ -118,7 +118,9 @@ func (dst *Text) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/text_array.go b/pgtype/text_array.go index a6bd4724..8a573d83 100644 --- a/pgtype/text_array.go +++ b/pgtype/text_array.go @@ -308,7 +308,9 @@ func (dst *TextArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/tid.go b/pgtype/tid.go index 7976afde..7456b155 100644 --- a/pgtype/tid.go +++ b/pgtype/tid.go @@ -134,7 +134,9 @@ func (dst *Tid) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/timestamp.go b/pgtype/timestamp.go index 694b63c0..4fb10abc 100644 --- a/pgtype/timestamp.go +++ b/pgtype/timestamp.go @@ -201,7 +201,9 @@ func (dst *Timestamp) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) case time.Time: *dst = Timestamp{Time: src, Status: Present} return nil diff --git a/pgtype/timestamp_array.go b/pgtype/timestamp_array.go index 2046c387..49815dae 100644 --- a/pgtype/timestamp_array.go +++ b/pgtype/timestamp_array.go @@ -309,7 +309,9 @@ func (dst *TimestampArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/timestamptz.go b/pgtype/timestamptz.go index 3c76ec03..8606b2f2 100644 --- a/pgtype/timestamptz.go +++ b/pgtype/timestamptz.go @@ -197,7 +197,9 @@ func (dst *Timestamptz) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) case time.Time: *dst = Timestamptz{Time: src, Status: Present} return nil diff --git a/pgtype/timestamptz_array.go b/pgtype/timestamptz_array.go index fd58d3be..bf983b6b 100644 --- a/pgtype/timestamptz_array.go +++ b/pgtype/timestamptz_array.go @@ -309,7 +309,9 @@ func (dst *TimestamptzArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/tsrange.go b/pgtype/tsrange.go index 78a94af2..429a5cbe 100644 --- a/pgtype/tsrange.go +++ b/pgtype/tsrange.go @@ -106,7 +106,7 @@ func (dst *Tsrange) DecodeBinary(ci *ConnInfo, src []byte) error { return nil } -func (src *Tsrange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Tsrange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -166,7 +166,7 @@ func (src *Tsrange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { return false, nil } -func (src *Tsrange) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Tsrange) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -256,13 +256,15 @@ func (dst *Tsrange) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) } // Value implements the database/sql/driver Valuer interface. -func (src *Tsrange) Value() (driver.Value, error) { +func (src Tsrange) Value() (driver.Value, error) { return EncodeValueText(src) } diff --git a/pgtype/tstzrange.go b/pgtype/tstzrange.go index d1fc7326..f03a9f65 100644 --- a/pgtype/tstzrange.go +++ b/pgtype/tstzrange.go @@ -106,7 +106,7 @@ func (dst *Tstzrange) DecodeBinary(ci *ConnInfo, src []byte) error { return nil } -func (src *Tstzrange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Tstzrange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -166,7 +166,7 @@ func (src *Tstzrange) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) { return false, nil } -func (src *Tstzrange) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { +func (src Tstzrange) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) { switch src.Status { case Null: return true, nil @@ -256,13 +256,15 @@ func (dst *Tstzrange) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) } // Value implements the database/sql/driver Valuer interface. -func (src *Tstzrange) Value() (driver.Value, error) { +func (src Tstzrange) Value() (driver.Value, error) { return EncodeValueText(src) } diff --git a/pgtype/typed_array.go.erb b/pgtype/typed_array.go.erb index 2a38ed82..6752bd5b 100644 --- a/pgtype/typed_array.go.erb +++ b/pgtype/typed_array.go.erb @@ -310,7 +310,9 @@ func (dst *<%= pgtype_array_type %>) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/typed_range.go.erb b/pgtype/typed_range.go.erb index e46f71c7..49db1b1d 100644 --- a/pgtype/typed_range.go.erb +++ b/pgtype/typed_range.go.erb @@ -256,7 +256,9 @@ func (dst *<%= range_type %>) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/uuid.go b/pgtype/uuid.go index c830c086..a4a93ab3 100644 --- a/pgtype/uuid.go +++ b/pgtype/uuid.go @@ -161,7 +161,9 @@ func (dst *Uuid) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/varbit.go b/pgtype/varbit.go index 00c34e10..b986f02a 100644 --- a/pgtype/varbit.go +++ b/pgtype/varbit.go @@ -72,10 +72,7 @@ func (dst *Varbit) DecodeBinary(ci *ConnInfo, src []byte) error { bitLen := int32(binary.BigEndian.Uint32(src)) rp := 4 - buf := make([]byte, len(src[rp:])) - copy(buf, src[rp:]) - - *dst = Varbit{Bytes: buf, Len: bitLen, Status: Present} + *dst = Varbit{Bytes: src[rp:], Len: bitLen, Status: Present} return nil } @@ -129,7 +126,9 @@ func (dst *Varbit) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) diff --git a/pgtype/varchar_array.go b/pgtype/varchar_array.go index 9ca16d7e..d84fac02 100644 --- a/pgtype/varchar_array.go +++ b/pgtype/varchar_array.go @@ -308,7 +308,9 @@ func (dst *VarcharArray) Scan(src interface{}) error { case string: return dst.DecodeText(nil, []byte(src)) case []byte: - return dst.DecodeText(nil, src) + srcCopy := make([]byte, len(src)) + copy(srcCopy, src) + return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src)