From c6cb362b189885af1a7467b35c116a716c504fbb Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Fri, 19 May 2017 17:31:22 -0500 Subject: [PATCH] Add flush and close messages to pgproto3 --- pgproto3/backend.go | 6 +++++ pgproto3/close.go | 60 +++++++++++++++++++++++++++++++++++++++++++++ pgproto3/flush.go | 29 ++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 pgproto3/close.go create mode 100644 pgproto3/flush.go diff --git a/pgproto3/backend.go b/pgproto3/backend.go index bd477315..df66a799 100644 --- a/pgproto3/backend.go +++ b/pgproto3/backend.go @@ -14,8 +14,10 @@ type Backend struct { // Frontend message flyweights bind Bind + _close Close describe Describe execute Execute + flush Flush parse Parse passwordMessage PasswordMessage query Query @@ -72,10 +74,14 @@ func (b *Backend) Receive() (FrontendMessage, error) { switch msgType { case 'B': msg = &b.bind + case 'C': + msg = &b._close case 'D': msg = &b.describe case 'E': msg = &b.execute + case 'H': + msg = &b.flush case 'P': msg = &b.parse case 'p': diff --git a/pgproto3/close.go b/pgproto3/close.go new file mode 100644 index 00000000..454ef68e --- /dev/null +++ b/pgproto3/close.go @@ -0,0 +1,60 @@ +package pgproto3 + +import ( + "bytes" + "encoding/binary" + "encoding/json" +) + +type Close struct { + ObjectType byte // 'S' = prepared statement, 'P' = portal + Name string +} + +func (*Close) Frontend() {} + +func (dst *Close) Decode(src []byte) error { + if len(src) < 2 { + return &invalidMessageFormatErr{messageType: "Close"} + } + + dst.ObjectType = src[0] + rp := 1 + + idx := bytes.IndexByte(src[rp:], 0) + if idx != len(src[rp:])-1 { + return &invalidMessageFormatErr{messageType: "Close"} + } + + dst.Name = string(src[rp : len(src)-1]) + + return nil +} + +func (src *Close) MarshalBinary() ([]byte, error) { + var bigEndian BigEndianBuf + buf := &bytes.Buffer{} + + buf.WriteByte('C') + buf.Write(bigEndian.Uint32(0)) + + buf.WriteByte(src.ObjectType) + buf.WriteString(src.Name) + buf.WriteByte(0) + + binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1)) + + return buf.Bytes(), nil +} + +func (src *Close) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type string + ObjectType string + Name string + }{ + Type: "Close", + ObjectType: string(src.ObjectType), + Name: src.Name, + }) +} diff --git a/pgproto3/flush.go b/pgproto3/flush.go new file mode 100644 index 00000000..d26f5c0c --- /dev/null +++ b/pgproto3/flush.go @@ -0,0 +1,29 @@ +package pgproto3 + +import ( + "encoding/json" +) + +type Flush struct{} + +func (*Flush) Frontend() {} + +func (dst *Flush) Decode(src []byte) error { + if len(src) != 0 { + return &invalidMessageLenErr{messageType: "Flush", expectedLen: 0, actualLen: len(src)} + } + + return nil +} + +func (src *Flush) MarshalBinary() ([]byte, error) { + return []byte{'H', 0, 0, 0, 4}, nil +} + +func (src *Flush) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type string + }{ + Type: "Flush", + }) +}