From 0e8f00e11c89c8d1adcd6d0aba5ee4c6a74cfcb1 Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Thu, 11 Apr 2013 20:22:55 -0500 Subject: [PATCH] Added understanding of error messages from server --- conn.go | 21 +++++++++++++++++++++ conn_test.go | 7 +++++++ messages.go | 11 +++++++++++ 3 files changed, 39 insertions(+) diff --git a/conn.go b/conn.go index 40c5174f..95011782 100644 --- a/conn.go +++ b/conn.go @@ -132,6 +132,8 @@ func (c *conn) processContextFreeMsg(t byte, r *messageReader) (err error) { case 'S': c.rxParameterStatus(r) return nil + case errorResponse: + return c.rxErrorResponse(r) default: return fmt.Errorf("Received unknown message type: %c", t) } @@ -190,6 +192,25 @@ func (c *conn) rxParameterStatus(r *messageReader) { c.runtimeParams[key] = value } +func (c *conn) rxErrorResponse(r *messageReader) (err PgError) { + for { + switch r.readByte() { + case 'S': + err.Severity = r.readString() + case 'C': + err.Code = r.readString() + case 'M': + err.Message = r.readString() + case 0: // End of error message + return + default: // Ignore other error fields + r.readString(); + } + } + + panic("Unreachable") +} + func (c *conn) rxBackendKeyData(r *messageReader) { c.pid = r.readInt32() c.secretKey = r.readInt32() diff --git a/conn_test.go b/conn_test.go index 1ce520f9..48f82b17 100644 --- a/conn_test.go +++ b/conn_test.go @@ -34,6 +34,13 @@ func TestConnect(t *testing.T) { } } +func TestConnectWithInvalidUser(t *testing.T) { + _, err := Connect(map[string]string{"socket": "/private/tmp/.s.PGSQL.5432", "user": "invalid_user", "database": "pgx_test"}) + pgErr := err.(PgError) + if pgErr.Code != "28000" { + t.Fatal("Did not receive expected error when connecting with invalid user") + } +} func TestQuery(t *testing.T) { conn, err := Connect(map[string]string{"socket": "/private/tmp/.s.PGSQL.5432", "user": "pgx", "database": "pgx_test"}) if err != nil { diff --git a/messages.go b/messages.go index bbc145fc..349e4e09 100644 --- a/messages.go +++ b/messages.go @@ -15,6 +15,7 @@ const ( rowDescription = 'T' dataRow = 'D' commandComplete = 'C' + errorResponse = 'E' ) type startupMessage struct { @@ -50,3 +51,13 @@ type fieldDescription struct { modifier int32 formatCode int16 } + +type PgError struct { + Severity string + Code string + Message string +} + +func (self PgError) Error() string { + return self.Severity + ": " + self.Message + " (SQLSTATE " + self.Code + ")" +}