diff --git a/connection_test.go b/connection_test.go index bf6ab11c..81447574 100644 --- a/connection_test.go +++ b/connection_test.go @@ -1,6 +1,7 @@ package pgx import ( + "bytes" "testing" ) @@ -291,6 +292,7 @@ func TestPrepare(t *testing.T) { if err != nil { t.Fatal("Unable to establish connection") } + defer conn.Close() testTranscode := func(sql string, value interface{}) { if err = conn.Prepare("testTranscode", sql); err != nil { @@ -313,7 +315,6 @@ func TestPrepare(t *testing.T) { t.Errorf("Expected: %#v Received: %#v", value, result) } } - } // Test parameter encoding and decoding for simple supported data types @@ -329,7 +330,33 @@ func TestPrepare(t *testing.T) { // Ensure that unknown types are just treated as strings testTranscode("select $1::point", "(0,0)") - // case []byte: - // s = `E'\\x` + hex.EncodeToString(arg) + `'` + if err = conn.Prepare("testByteSliceTranscode", "select $1::bytea"); err != nil { + t.Errorf("Unable to prepare statement: %v", err) + return + } + defer func() { + err := conn.Deallocate("testByteSliceTranscode") + if err != nil { + t.Errorf("Deallocate failed: %v", err) + } + }() + bytea := make([]byte, 4) + bytea[0] = 0 // 0x00 + bytea[1] = 15 // 0x0F + bytea[2] = 255 // 0xFF + bytea[3] = 17 // 0x11 + + if conn.SanitizeSql("select $1", bytea) != `select E'\\x000fff11'` { + t.Error("Failed to sanitize []byte") + } + var result interface{} + result, err = conn.SelectValue("testByteSliceTranscode", bytea) + if err != nil { + t.Errorf("%v while running %v", err, "testByteSliceTranscode") + } else { + if bytes.Compare(result.([]byte), bytea) != 0 { + t.Errorf("Expected: %#v Received: %#v", bytea, result) + } + } } diff --git a/value_transcoder.go b/value_transcoder.go index 45dfa8f9..0fa98ff5 100644 --- a/value_transcoder.go +++ b/value_transcoder.go @@ -3,6 +3,7 @@ package pgx import ( "bytes" "encoding/binary" + "encoding/hex" "fmt" "strconv" ) @@ -25,6 +26,12 @@ func init() { DecodeText: decodeBoolFromText, EncodeTo: encodeBool} + // bytea + valueTranscoders[oid(17)] = &valueTranscoder{ + DecodeText: decodeByteaFromText, + EncodeTo: encodeBytea, + EncodeFormat: 1} + // int8 valueTranscoders[oid(20)] = &valueTranscoder{ DecodeText: decodeInt8FromText, @@ -170,3 +177,18 @@ func encodeText(buf *bytes.Buffer, value interface{}) { binary.Write(buf, binary.BigEndian, int32(len(s))) buf.WriteString(s) } + +func decodeByteaFromText(mr *MessageReader, size int32) interface{} { + s := mr.ReadByteString(size) + b, err := hex.DecodeString(s[2:]) + if err != nil { + panic("Can't decode byte array") + } + return b +} + +func encodeBytea(buf *bytes.Buffer, value interface{}) { + b := value.([]byte) + binary.Write(buf, binary.BigEndian, int32(len(b))) + buf.Write(b) +}