diff --git a/bench_test.go b/bench_test.go index 80d332e5..1264b65e 100644 --- a/bench_test.go +++ b/bench_test.go @@ -1,7 +1,6 @@ package pgx_test import ( - "fmt" "github.com/JackC/pgx" "math/rand" "testing" @@ -22,7 +21,7 @@ func createNarrowTestData(b *testing.B, conn *pgx.Connection) { return } - if _, err := conn.Execute(` + mustExecute(b, conn, ` drop table if exists narrow; create table narrow( @@ -38,9 +37,7 @@ func createNarrowTestData(b *testing.B, conn *pgx.Connection) { from generate_series(1, 10000); analyze narrow; - `); err != nil { - panic(fmt.Sprintf("Unable to create narrow test data: %v", err)) - } + `) mustPrepare(b, conn, "getNarrowById", "select * from narrow where id=$1") mustPrepare(b, conn, "getMultipleNarrowById", "select * from narrow where id between $1 and $2") @@ -64,7 +61,7 @@ func restoreBinaryEncoders(encoders map[pgx.Oid]func(*pgx.MessageReader, int32) } func BenchmarkSelectRowSimpleNarrow(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createNarrowTestData(b, conn) // Get random ids outside of timing @@ -80,7 +77,7 @@ func BenchmarkSelectRowSimpleNarrow(b *testing.B) { } func BenchmarkSelectRowPreparedNarrow(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createNarrowTestData(b, conn) // Get random ids outside of timing @@ -96,7 +93,7 @@ func BenchmarkSelectRowPreparedNarrow(b *testing.B) { } func BenchmarkSelectRowsSimpleNarrow(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createNarrowTestData(b, conn) // Get random ids outside of timing @@ -112,7 +109,7 @@ func BenchmarkSelectRowsSimpleNarrow(b *testing.B) { } func BenchmarkSelectRowsPreparedNarrow(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createNarrowTestData(b, conn) // Get random ids outside of timing @@ -199,7 +196,7 @@ func createJoinsTestData(b *testing.B, conn *pgx.Connection) { } func BenchmarkSelectRowsSimpleJoins(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createJoinsTestData(b, conn) sql := ` @@ -219,7 +216,7 @@ func BenchmarkSelectRowsSimpleJoins(b *testing.B) { } func BenchmarkSelectRowsPreparedJoins(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createJoinsTestData(b, conn) b.ResetTimer() @@ -254,7 +251,7 @@ func createInt2TextVsBinaryTestData(b *testing.B, conn *pgx.Connection) { } func BenchmarkInt2Text(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createInt2TextVsBinaryTestData(b, conn) encoders := removeBinaryEncoders() @@ -270,7 +267,7 @@ func BenchmarkInt2Text(b *testing.B) { } func BenchmarkInt2Binary(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createInt2TextVsBinaryTestData(b, conn) mustPrepare(b, conn, "selectInt16", "select * from t") defer func() { conn.Deallocate("selectInt16") }() @@ -307,7 +304,7 @@ func createInt4TextVsBinaryTestData(b *testing.B, conn *pgx.Connection) { } func BenchmarkInt4Text(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createInt4TextVsBinaryTestData(b, conn) encoders := removeBinaryEncoders() @@ -323,7 +320,7 @@ func BenchmarkInt4Text(b *testing.B) { } func BenchmarkInt4Binary(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createInt4TextVsBinaryTestData(b, conn) mustPrepare(b, conn, "selectInt32", "select * from t") defer func() { conn.Deallocate("selectInt32") }() @@ -360,7 +357,7 @@ func createInt8TextVsBinaryTestData(b *testing.B, conn *pgx.Connection) { } func BenchmarkInt8Text(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createInt8TextVsBinaryTestData(b, conn) encoders := removeBinaryEncoders() @@ -376,7 +373,7 @@ func BenchmarkInt8Text(b *testing.B) { } func BenchmarkInt8Binary(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createInt8TextVsBinaryTestData(b, conn) mustPrepare(b, conn, "selectInt64", "select * from t") defer func() { conn.Deallocate("selectInt64") }() @@ -413,7 +410,7 @@ func createFloat4TextVsBinaryTestData(b *testing.B, conn *pgx.Connection) { } func BenchmarkFloat4Text(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createFloat4TextVsBinaryTestData(b, conn) encoders := removeBinaryEncoders() @@ -429,7 +426,7 @@ func BenchmarkFloat4Text(b *testing.B) { } func BenchmarkFloat4Binary(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createFloat4TextVsBinaryTestData(b, conn) mustPrepare(b, conn, "selectFloat32", "select * from t") defer func() { conn.Deallocate("selectFloat32") }() @@ -466,7 +463,7 @@ func createFloat8TextVsBinaryTestData(b *testing.B, conn *pgx.Connection) { } func BenchmarkFloat8Text(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createFloat8TextVsBinaryTestData(b, conn) encoders := removeBinaryEncoders() @@ -482,7 +479,7 @@ func BenchmarkFloat8Text(b *testing.B) { } func BenchmarkFloat8Binary(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createFloat8TextVsBinaryTestData(b, conn) mustPrepare(b, conn, "selectFloat32", "select * from t") defer func() { conn.Deallocate("selectFloat32") }() @@ -519,7 +516,7 @@ func createBoolTextVsBinaryTestData(b *testing.B, conn *pgx.Connection) { } func BenchmarkBoolText(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createBoolTextVsBinaryTestData(b, conn) encoders := removeBinaryEncoders() @@ -535,7 +532,7 @@ func BenchmarkBoolText(b *testing.B) { } func BenchmarkBoolBinary(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createBoolTextVsBinaryTestData(b, conn) mustPrepare(b, conn, "selectBool", "select * from t") defer func() { conn.Deallocate("selectBool") }() @@ -576,7 +573,7 @@ func createTimestampTzTextVsBinaryTestData(b *testing.B, conn *pgx.Connection) { } func BenchmarkTimestampTzText(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createTimestampTzTextVsBinaryTestData(b, conn) encoders := removeBinaryEncoders() @@ -592,7 +589,7 @@ func BenchmarkTimestampTzText(b *testing.B) { } func BenchmarkTimestampTzBinary(b *testing.B) { - conn := getSharedConnection() + conn := getSharedConnection(b) createTimestampTzTextVsBinaryTestData(b, conn) mustPrepare(b, conn, "selectTimestampTz", "select * from t") defer func() { conn.Deallocate("selectTimestampTz") }() diff --git a/connection.go b/connection.go index 2c824809..750e01e9 100644 --- a/connection.go +++ b/connection.go @@ -73,6 +73,12 @@ func (e UnexpectedColumnCountError) Error() string { return fmt.Sprintf("Expected result to have %d column(s), instead it has %d", e.ExpectedCount, e.ActualCount) } +type ProtocolError string + +func (e ProtocolError) Error() string { + return string(e) +} + // sharedBufferSize is the default number of bytes of work buffer per connection const sharedBufferSize = 1024 @@ -171,7 +177,11 @@ func (c *Connection) SelectFunc(sql string, onDataRow func(*DataRowReader) error fields = c.rxRowDescription(r) case dataRow: if err == nil { - err = onDataRow(newDataRowReader(r, fields)) + var drr *DataRowReader + drr, err = newDataRowReader(r, fields) + if err == nil { + err = onDataRow(drr) + } } case commandComplete: case bindComplete: @@ -393,7 +403,10 @@ func (c *Connection) sendQuery(sql string, arguments ...interface{}) (err error) func (c *Connection) sendSimpleQuery(sql string, arguments ...interface{}) (err error) { if len(arguments) > 0 { - sql = c.SanitizeSql(sql, arguments...) + sql, err = c.SanitizeSql(sql, arguments...) + if err != nil { + return + } } buf := c.getBuf() diff --git a/connection_pool_test.go b/connection_pool_test.go index a030c98e..ace28259 100644 --- a/connection_pool_test.go +++ b/connection_pool_test.go @@ -6,10 +6,10 @@ import ( "testing" ) -func createConnectionPool(maxConnections int) *pgx.ConnectionPool { +func createConnectionPool(t *testing.T, maxConnections int) *pgx.ConnectionPool { pool, err := pgx.NewConnectionPool(*defaultConnectionParameters, maxConnections) if err != nil { - panic("Unable to create connection pool") + t.Fatalf("Unable to create connection pool: %v", err) } return pool } @@ -30,7 +30,7 @@ func TestPoolAcquireAndReleaseCycle(t *testing.T) { maxConnections := 2 incrementCount := int32(100) completeSync := make(chan int) - pool := createConnectionPool(maxConnections) + pool := createConnectionPool(t, maxConnections) defer pool.Close() acquireAll := func() (connections []*pgx.Connection) { @@ -99,7 +99,7 @@ func TestPoolAcquireAndReleaseCycle(t *testing.T) { } func TestPoolReleaseWithTransactions(t *testing.T) { - pool := createConnectionPool(1) + pool := createConnectionPool(t, 1) defer pool.Close() var err error diff --git a/connection_test.go b/connection_test.go index 486abe5c..d9844768 100644 --- a/connection_test.go +++ b/connection_test.go @@ -124,7 +124,7 @@ func TestConnectWithMD5Password(t *testing.T) { } func TestExecute(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) if results := mustExecute(t, conn, "create temporary table foo(id integer primary key);"); results != "CREATE TABLE" { t.Error("Unexpected results from Execute") @@ -167,7 +167,7 @@ func TestExecuteFailure(t *testing.T) { } func TestSelectFunc(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) var sum, rowCount int32 onDataRow := func(r *pgx.DataRowReader) error { @@ -206,14 +206,18 @@ func TestSelectFuncFailure(t *testing.T) { } func Example_connectionSelectFunc() { - conn := getSharedConnection() + conn, err := pgx.Connect(*defaultConnectionParameters) + if err != nil { + fmt.Printf("Unable to establish connection: %v", err) + return + } onDataRow := func(r *pgx.DataRowReader) error { fmt.Println(r.ReadValue()) return nil } - err := conn.SelectFunc("select generate_series(1,$1)", onDataRow, 5) + err = conn.SelectFunc("select generate_series(1,$1)", onDataRow, 5) if err != nil { fmt.Println(err) } @@ -226,7 +230,7 @@ func Example_connectionSelectFunc() { } func TestSelectRows(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) rows := mustSelectRows(t, conn, "select $1 as name, null as position", "Jack") @@ -248,7 +252,7 @@ func TestSelectRows(t *testing.T) { } func TestSelectRow(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) row := mustSelectRow(t, conn, "select $1 as name, null as position", "Jack") if row["name"] != "Jack" { @@ -275,7 +279,7 @@ func TestSelectRow(t *testing.T) { } func TestConnectionSelectValue(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) test := func(sql string, expected interface{}, arguments ...interface{}) { v, err := conn.SelectValue(sql, arguments...) @@ -315,7 +319,7 @@ func TestConnectionSelectValue(t *testing.T) { } func TestSelectValues(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) test := func(sql string, expected []interface{}, arguments ...interface{}) { values, err := conn.SelectValues(sql, arguments...) @@ -406,7 +410,9 @@ func TestPrepare(t *testing.T) { bytea[2] = 255 // 0xFF bytea[3] = 17 // 0x11 - if conn.SanitizeSql("select $1", bytea) != `select E'\\x000fff11'` { + if sql, err := conn.SanitizeSql("select $1", bytea); err != nil { + t.Errorf("Error sanitizing []byte: %v", err) + } else if sql != `select E'\\x000fff11'` { t.Error("Failed to sanitize []byte") } var result interface{} @@ -579,7 +585,7 @@ func TestListenNotify(t *testing.T) { t.Fatalf("Unable to start listening: %v", err) } - notifier := getSharedConnection() + notifier := getSharedConnection(t) mustExecute(t, notifier, "notify chat") // when notification is waiting on the socket to be read diff --git a/data_row_reader.go b/data_row_reader.go index 1e6f199f..32cbcbc3 100644 --- a/data_row_reader.go +++ b/data_row_reader.go @@ -1,5 +1,9 @@ package pgx +import ( + "fmt" +) + // DataRowReader is used by SelectFunc to process incoming rows. type DataRowReader struct { mr *MessageReader @@ -7,14 +11,14 @@ type DataRowReader struct { currentFieldIdx int } -func newDataRowReader(mr *MessageReader, fields []FieldDescription) (r *DataRowReader) { +func newDataRowReader(mr *MessageReader, fields []FieldDescription) (r *DataRowReader, err error) { r = new(DataRowReader) r.mr = mr r.fields = fields fieldCount := int(mr.ReadInt16()) if fieldCount != len(fields) { - panic("Row description field count and data row field count do not match") + return nil, ProtocolError(fmt.Sprintf("Row description field count (%v) and data row field count (%v) do not match", len(fields), fieldCount)) } return @@ -34,7 +38,7 @@ func (r *DataRowReader) ReadValue() interface{} { case 1: return vt.DecodeBinary(r.mr, size) default: - panic("Unknown format") + return ProtocolError(fmt.Sprintf("Unknown field description format code: %v", fieldDescription.FormatCode)) } } else { return r.mr.ReadString(size) diff --git a/data_row_reader_test.go b/data_row_reader_test.go index 25b0ce38..35980624 100644 --- a/data_row_reader_test.go +++ b/data_row_reader_test.go @@ -6,7 +6,7 @@ import ( ) func TestDataRowReaderReadValue(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) test := func(sql string, expected interface{}) { var v interface{} diff --git a/example_value_transcoder_test.go b/example_value_transcoder_test.go index 662c2658..c4e23575 100644 --- a/example_value_transcoder_test.go +++ b/example_value_transcoder_test.go @@ -23,7 +23,11 @@ func Example_customValueTranscoder() { DecodeText: decodePointFromText, EncodeTo: encodePoint} - conn := getSharedConnection() + conn, err := pgx.Connect(*defaultConnectionParameters) + if err != nil { + fmt.Printf("Unable to establish connection: %v", err) + return + } v, _ := conn.SelectValue("select point(1.5,2.5)") fmt.Println(v) @@ -35,18 +39,18 @@ func decodePointFromText(mr *pgx.MessageReader, size int32) interface{} { s := mr.ReadString(size) match := pointRegexp.FindStringSubmatch(s) if match == nil { - panic(fmt.Sprintf("Received invalid point: %v", s)) + return pgx.ProtocolError(fmt.Sprintf("Received invalid point: %v", s)) } var err error var p Point p.x, err = strconv.ParseFloat(match[1], 64) if err != nil { - panic(fmt.Sprintf("Received invalid point: %v", s)) + return pgx.ProtocolError(fmt.Sprintf("Received invalid point: %v", s)) } p.y, err = strconv.ParseFloat(match[2], 64) if err != nil { - panic(fmt.Sprintf("Received invalid point: %v", s)) + return pgx.ProtocolError(fmt.Sprintf("Received invalid point: %v", s)) } return p } diff --git a/helper_test.go b/helper_test.go index fed4dc39..8fca4223 100644 --- a/helper_test.go +++ b/helper_test.go @@ -10,12 +10,12 @@ type test interface { var sharedConnection *pgx.Connection -func getSharedConnection() (c *pgx.Connection) { +func getSharedConnection(t test) (c *pgx.Connection) { if sharedConnection == nil { var err error sharedConnection, err = pgx.Connect(*defaultConnectionParameters) if err != nil { - panic("Unable to establish connection") + t.Fatalf("Unable to establish connection: %v", err) } } diff --git a/sanitize.go b/sanitize.go index f5ac49dc..7a07352f 100644 --- a/sanitize.go +++ b/sanitize.go @@ -2,7 +2,7 @@ package pgx import ( "encoding/hex" - "reflect" + "fmt" "regexp" "strconv" "strings" @@ -28,7 +28,7 @@ func (c *Connection) QuoteIdentifier(input string) (output string) { // SanitizeSql substitutely args positionaly into sql. Placeholder values are // $ prefixed integers like $1, $2, $3, etc. args are sanitized and quoted as // appropriate. -func (c *Connection) SanitizeSql(sql string, args ...interface{}) (output string) { +func (c *Connection) SanitizeSql(sql string, args ...interface{}) (output string, err error) { replacer := func(match string) (replacement string) { n, _ := strconv.ParseInt(match[1:], 10, 0) switch arg := args[n-1].(type) { @@ -63,7 +63,8 @@ func (c *Connection) SanitizeSql(sql string, args ...interface{}) (output string case []byte: return `E'\\x` + hex.EncodeToString(arg) + `'` default: - panic("Unable to sanitize type: " + reflect.TypeOf(arg).String()) + err = fmt.Errorf("Unable to sanitize type: %T", arg) + return "" } } diff --git a/sanitize_test.go b/sanitize_test.go index 36123091..1bd18270 100644 --- a/sanitize_test.go +++ b/sanitize_test.go @@ -5,7 +5,7 @@ import ( ) func TestQuoteString(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) if conn.QuoteString("test") != "'test'" { t.Error("Failed to quote string") @@ -17,22 +17,22 @@ func TestQuoteString(t *testing.T) { } func TestSanitizeSql(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) - if conn.SanitizeSql("select $1", "Jack's") != "select 'Jack''s'" { - t.Error("Failed to sanitize string") + if san, err := conn.SanitizeSql("select $1", "Jack's"); err != nil || san != "select 'Jack''s'" { + t.Errorf("Failed to sanitize string: %v - %v", san, err) } - if conn.SanitizeSql("select $1", 42) != "select 42" { - t.Error("Failed to pass through integer") + if san, err := conn.SanitizeSql("select $1", 42); err != nil || san != "select 42" { + t.Errorf("Failed to pass through integer: %v - %v", san, err) } - if conn.SanitizeSql("select $1", 1.23) != "select 1.23" { - t.Error("Failed to pass through float") + if san, err := conn.SanitizeSql("select $1", 1.23); err != nil || san != "select 1.23" { + t.Errorf("Failed to pass through float: %v - %v", san, err) } - if conn.SanitizeSql("select $1, $2, $3", "Jack's", 42, 1.23) != "select 'Jack''s', 42, 1.23" { - t.Error("Failed to sanitize multiple params") + if san, err := conn.SanitizeSql("select $1, $2, $3", "Jack's", 42, 1.23); err != nil || san != "select 'Jack''s', 42, 1.23" { + t.Errorf("Failed to sanitize multiple params: %v - %v", san, err) } bytea := make([]byte, 4) @@ -41,7 +41,7 @@ func TestSanitizeSql(t *testing.T) { bytea[2] = 255 // 0xFF bytea[3] = 17 // 0x11 - if conn.SanitizeSql("select $1", bytea) != `select E'\\x000fff11'` { - t.Error("Failed to sanitize []byte") + if san, err := conn.SanitizeSql("select $1", bytea); err != nil || san != `select E'\\x000fff11'` { + t.Errorf("Failed to sanitize []byte: %v - %v", san, err) } } diff --git a/value_transcoder.go b/value_transcoder.go index e990774b..2a16184a 100644 --- a/value_transcoder.go +++ b/value_transcoder.go @@ -112,13 +112,13 @@ func decodeBoolFromText(mr *MessageReader, size int32) interface{} { case "f": return false default: - panic(fmt.Sprintf("Received invalid bool: %v", s)) + return ProtocolError(fmt.Sprintf("Received invalid bool: %v", s)) } } func decodeBoolFromBinary(mr *MessageReader, size int32) interface{} { if size != 1 { - panic("Received an invalid size for an bool") + return ProtocolError(fmt.Sprintf("Received an invalid size for an bool: %d", size)) } b := mr.ReadByte() return b != 0 @@ -138,14 +138,14 @@ func decodeInt8FromText(mr *MessageReader, size int32) interface{} { s := mr.ReadString(size) n, err := strconv.ParseInt(s, 10, 64) if err != nil { - panic(fmt.Sprintf("Received invalid int8: %v", s)) + return ProtocolError(fmt.Sprintf("Received invalid int8: %v", s)) } return n } func decodeInt8FromBinary(mr *MessageReader, size int32) interface{} { if size != 8 { - panic("Received an invalid size for an int8") + return ProtocolError(fmt.Sprintf("Received an invalid size for an int8: %d", size)) } return mr.ReadInt64() } @@ -160,14 +160,14 @@ func decodeInt2FromText(mr *MessageReader, size int32) interface{} { s := mr.ReadString(size) n, err := strconv.ParseInt(s, 10, 16) if err != nil { - panic(fmt.Sprintf("Received invalid int2: %v", s)) + return ProtocolError(fmt.Sprintf("Received invalid int2: %v", s)) } return int16(n) } func decodeInt2FromBinary(mr *MessageReader, size int32) interface{} { if size != 2 { - panic("Received an invalid size for an int8") + return ProtocolError(fmt.Sprintf("Received an invalid size for an int2: %d", size)) } return mr.ReadInt16() } @@ -182,14 +182,14 @@ func decodeInt4FromText(mr *MessageReader, size int32) interface{} { s := mr.ReadString(size) n, err := strconv.ParseInt(s, 10, 32) if err != nil { - panic(fmt.Sprintf("Received invalid int4: %v", s)) + return ProtocolError(fmt.Sprintf("Received invalid int4: %v", s)) } return int32(n) } func decodeInt4FromBinary(mr *MessageReader, size int32) interface{} { if size != 4 { - panic("Received an invalid size for an int4") + return ProtocolError(fmt.Sprintf("Received an invalid size for an int4: %d", size)) } return mr.ReadInt32() } @@ -204,14 +204,14 @@ func decodeFloat4FromText(mr *MessageReader, size int32) interface{} { s := mr.ReadString(size) n, err := strconv.ParseFloat(s, 32) if err != nil { - panic(fmt.Sprintf("Received invalid float4: %v", s)) + return ProtocolError(fmt.Sprintf("Received invalid float4: %v", s)) } return float32(n) } func decodeFloat4FromBinary(mr *MessageReader, size int32) interface{} { if size != 4 { - panic("Received an invalid size for an float4") + return ProtocolError(fmt.Sprintf("Received an invalid size for an float4: %d", size)) } i := mr.ReadInt32() @@ -229,14 +229,14 @@ func decodeFloat8FromText(mr *MessageReader, size int32) interface{} { s := mr.ReadString(size) v, err := strconv.ParseFloat(s, 64) if err != nil { - panic(fmt.Sprintf("Received invalid float8: %v", s)) + return ProtocolError(fmt.Sprintf("Received invalid float8: %v", s)) } return v } func decodeFloat8FromBinary(mr *MessageReader, size int32) interface{} { if size != 8 { - panic("Received an invalid size for an float4") + return ProtocolError(fmt.Sprintf("Received an invalid size for an float8: %d", size)) } i := mr.ReadInt64() @@ -264,7 +264,7 @@ func decodeByteaFromText(mr *MessageReader, size int32) interface{} { s := mr.ReadString(size) b, err := hex.DecodeString(s[2:]) if err != nil { - panic("Can't decode byte array") + return ProtocolError(fmt.Sprintf("Can't decode byte array: %v - %v", err, s)) } return b } @@ -279,7 +279,7 @@ func decodeDateFromText(mr *MessageReader, size int32) interface{} { s := mr.ReadString(size) t, err := time.ParseInLocation("2006-01-02", s, time.Local) if err != nil { - panic("Can't decode date") + return ProtocolError(fmt.Sprintf("Can't decode date: %v", s)) } return t } @@ -295,14 +295,14 @@ func decodeTimestampTzFromText(mr *MessageReader, size int32) interface{} { s := mr.ReadString(size) t, err := time.Parse("2006-01-02 15:04:05.999999-07", s) if err != nil { - panic(fmt.Sprintf("Can't decode timestamptz: %v", err)) + return ProtocolError(fmt.Sprintf("Can't decode timestamptz: %v - %v", err, s)) } return t } func decodeTimestampTzFromBinary(mr *MessageReader, size int32) interface{} { if size != 8 { - panic("Received an invalid size for an int8") + return ProtocolError(fmt.Sprintf("Received an invalid size for an int8: %d", size)) } microsecFromUnixEpochToY2K := int64(946684800 * 1000000) microsecSinceY2K := mr.ReadInt64() diff --git a/value_transcoder_test.go b/value_transcoder_test.go index c52307ab..0d0227a4 100644 --- a/value_transcoder_test.go +++ b/value_transcoder_test.go @@ -6,7 +6,7 @@ import ( ) func TestDateTranscode(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) actualDate := time.Date(2013, 1, 2, 0, 0, 0, 0, time.Local) @@ -34,7 +34,7 @@ func TestDateTranscode(t *testing.T) { } func TestTimestampTzTranscode(t *testing.T) { - conn := getSharedConnection() + conn := getSharedConnection(t) inputTime := time.Date(2013, 1, 2, 3, 4, 5, 6000, time.Local)