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:
committed by
Jack Christensen
parent
88b6398594
commit
1213b69774
+26
-17
@@ -7,23 +7,24 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ErrorResponse struct {
|
type ErrorResponse struct {
|
||||||
Severity string
|
Severity string
|
||||||
Code string
|
SeverityUnlocalized string // only in 9.6 and greater
|
||||||
Message string
|
Code string
|
||||||
Detail string
|
Message string
|
||||||
Hint string
|
Detail string
|
||||||
Position int32
|
Hint string
|
||||||
InternalPosition int32
|
Position int32
|
||||||
InternalQuery string
|
InternalPosition int32
|
||||||
Where string
|
InternalQuery string
|
||||||
SchemaName string
|
Where string
|
||||||
TableName string
|
SchemaName string
|
||||||
ColumnName string
|
TableName string
|
||||||
DataTypeName string
|
ColumnName string
|
||||||
ConstraintName string
|
DataTypeName string
|
||||||
File string
|
ConstraintName string
|
||||||
Line int32
|
File string
|
||||||
Routine string
|
Line int32
|
||||||
|
Routine string
|
||||||
|
|
||||||
UnknownFields map[byte]string
|
UnknownFields map[byte]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))
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user