2
0

Use flyweight pattern for pgproto3 messages

This commit is contained in:
Jack Christensen
2017-04-29 11:01:54 -05:00
parent 4e2900b774
commit de9bb7e6d8
+73 -30
View File
@@ -12,6 +12,29 @@ import (
type Frontend struct {
cr *chunkreader.ChunkReader
w io.Writer
// Backend message flyweights
authentication Authentication
backendKeyData BackendKeyData
bindComplete BindComplete
closeComplete CloseComplete
commandComplete CommandComplete
copyBothResponse CopyBothResponse
copyData CopyData
copyInResponse CopyInResponse
copyOutResponse CopyOutResponse
dataRow DataRow
emptyQueryResponse EmptyQueryResponse
errorResponse ErrorResponse
functionCallResponse FunctionCallResponse
noData NoData
noticeResponse NoticeResponse
notificationResponse NotificationResponse
parameterDescription ParameterDescription
parameterStatus ParameterStatus
parseComplete ParseComplete
readyForQuery ReadyForQuery
rowDescription RowDescription
}
func NewFrontend(r io.Reader, w io.Writer) (*Frontend, error) {
@@ -24,30 +47,6 @@ func (b *Frontend) Send(msg FrontendMessage) error {
}
func (b *Frontend) Receive() (BackendMessage, error) {
backendMessages := map[byte]BackendMessage{
'1': &ParseComplete{},
'2': &BindComplete{},
'3': &CloseComplete{},
'A': &NotificationResponse{},
'C': &CommandComplete{},
'd': &CopyData{},
'D': &DataRow{},
'E': &ErrorResponse{},
'G': &CopyInResponse{},
'H': &CopyOutResponse{},
'I': &EmptyQueryResponse{},
'K': &BackendKeyData{},
'n': &NoData{},
'N': &NoticeResponse{},
'R': &Authentication{},
'S': &ParameterStatus{},
't': &ParameterDescription{},
'T': &RowDescription{},
'V': &FunctionCallResponse{},
'W': &CopyBothResponse{},
'Z': &ReadyForQuery{},
}
header, err := b.cr.Next(5)
if err != nil {
return nil, err
@@ -56,15 +55,59 @@ func (b *Frontend) Receive() (BackendMessage, error) {
msgType := header[0]
bodyLen := int(binary.BigEndian.Uint32(header[1:])) - 4
var msg BackendMessage
switch msgType {
case '1':
msg = &b.parseComplete
case '2':
msg = &b.bindComplete
case '3':
msg = &b.closeComplete
case 'A':
msg = &b.notificationResponse
case 'C':
msg = &b.commandComplete
case 'd':
msg = &b.copyData
case 'D':
msg = &b.dataRow
case 'E':
msg = &b.errorResponse
case 'G':
msg = &b.copyInResponse
case 'H':
msg = &b.copyOutResponse
case 'I':
msg = &b.emptyQueryResponse
case 'K':
msg = &b.backendKeyData
case 'n':
msg = &b.noData
case 'N':
msg = &b.noticeResponse
case 'R':
msg = &b.authentication
case 'S':
msg = &b.parameterStatus
case 't':
msg = &b.parameterDescription
case 'T':
msg = &b.rowDescription
case 'V':
msg = &b.functionCallResponse
case 'W':
msg = &b.copyBothResponse
case 'Z':
msg = &b.readyForQuery
default:
return nil, fmt.Errorf("unknown message type: %c", msgType)
}
msgBody, err := b.cr.Next(bodyLen)
if err != nil {
return nil, err
}
if msg, ok := backendMessages[msgType]; ok {
err = msg.UnmarshalBinary(msgBody)
return msg, err
}
return nil, fmt.Errorf("unknown message type: %c", msgType)
err = msg.UnmarshalBinary(msgBody)
return msg, err
}