2
0

Add support to ErrorResponse for unlocalized severity

Add missing 'V' field for unlocalized severity added in PG versions 9.6
and greater. See https://www.postgresql.org/docs/current/protocol-error-fields.html
This commit is contained in:
Yuli Khodorkovskiy
2020-12-16 03:42:55 +00:00
committed by Jack Christensen
parent 88b6398594
commit 1213b69774
2 changed files with 63 additions and 17 deletions
+9
View File
@@ -8,6 +8,7 @@ import (
type ErrorResponse struct { type ErrorResponse struct {
Severity string Severity string
SeverityUnlocalized string // only in 9.6 and greater
Code string Code string
Message string Message string
Detail string Detail string
@@ -56,6 +57,8 @@ func (dst *ErrorResponse) Decode(src []byte) error {
switch k { switch k {
case 'S': case 'S':
dst.Severity = v dst.Severity = v
case 'V':
dst.SeverityUnlocalized = v
case 'C': case 'C':
dst.Code = v dst.Code = v
case 'M': case 'M':
@@ -123,6 +126,11 @@ func (src *ErrorResponse) marshalBinary(typeByte byte) []byte {
buf.WriteString(src.Severity) buf.WriteString(src.Severity)
buf.WriteByte(0) buf.WriteByte(0)
} }
if src.SeverityUnlocalized != "" {
buf.WriteByte('V')
buf.WriteString(src.SeverityUnlocalized)
buf.WriteByte(0)
}
if src.Code != "" { if src.Code != "" {
buf.WriteByte('C') buf.WriteByte('C')
buf.WriteString(src.Code) buf.WriteString(src.Code)
@@ -210,6 +218,7 @@ func (src *ErrorResponse) marshalBinary(typeByte byte) []byte {
buf.WriteString(v) buf.WriteString(v)
buf.WriteByte(0) buf.WriteByte(0)
} }
buf.WriteByte(0) buf.WriteByte(0)
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1)) binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
+37
View File
@@ -6,6 +6,7 @@ import (
"github.com/jackc/pgproto3/v2" "github.com/jackc/pgproto3/v2"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
type interruptReader struct { type interruptReader struct {
@@ -78,3 +79,39 @@ func TestFrontendReceiveUnexpectedEOF(t *testing.T) {
assert.Nil(t, msg) assert.Nil(t, msg)
assert.Equal(t, io.ErrUnexpectedEOF, err) assert.Equal(t, io.ErrUnexpectedEOF, err)
} }
func TestErrorResponse(t *testing.T) {
t.Parallel()
want := &pgproto3.ErrorResponse{
Severity: "ERROR",
SeverityUnlocalized: "ERROR",
Message: `column "foo" does not exist`,
File: "parse_relation.c",
Code: "42703",
Position: 8,
Line: 3513,
Routine: "errorMissingColumn",
}
raw := []byte{
'E', 0, 0, 0, 'f',
'S', 'E', 'R', 'R', 'O', 'R', 0,
'V', 'E', 'R', 'R', 'O', 'R', 0,
'C', '4', '2', '7', '0', '3', 0,
'M', 'c', 'o', 'l', 'u', 'm', 'n', 32, '"', 'f', 'o', 'o', '"', 32, 'd', 'o', 'e', 's', 32, 'n', 'o', 't', 32, 'e', 'x', 'i', 's', 't', 0,
'P', '8', 0,
'F', 'p', 'a', 'r', 's', 'e', '_', 'r', 'e', 'l', 'a', 't', 'i', 'o', 'n', '.', 'c', 0,
'L', '3', '5', '1', '3', 0,
'R', 'e', 'r', 'r', 'o', 'r', 'M', 'i', 's', 's', 'i', 'n', 'g', 'C', 'o', 'l', 'u', 'm', 'n', 0, 0,
}
server := &interruptReader{}
server.push(raw)
frontend := pgproto3.NewFrontend(pgproto3.NewChunkReader(server), nil)
got, err := frontend.Receive()
require.NoError(t, err)
assert.Equal(t, want, got)
}