summaryrefslogtreecommitdiff
path: root/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go')
-rw-r--r--vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go137
1 files changed, 112 insertions, 25 deletions
diff --git a/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go b/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
index 60c34ef02..b41abbe10 100644
--- a/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
+++ b/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
@@ -18,7 +18,8 @@ type Frontend struct {
// idle. Setting and unsetting tracer provides equivalent functionality to PQtrace and PQuntrace in libpq.
tracer *tracer
- wbuf []byte
+ wbuf []byte
+ encodeError error
// Backend message flyweights
authenticationOk AuthenticationOk
@@ -64,16 +65,26 @@ func NewFrontend(r io.Reader, w io.Writer) *Frontend {
return &Frontend{cr: cr, w: w}
}
-// Send sends a message to the backend (i.e. the server). The message is not guaranteed to be written until Flush is
-// called.
+// Send sends a message to the backend (i.e. the server). The message is buffered until Flush is called. Any error
+// encountered will be returned from Flush.
//
// Send can work with any FrontendMessage. Some commonly used message types such as Bind have specialized send methods
// such as SendBind. These methods should be preferred when the type of message is known up front (e.g. when building an
// extended query protocol query) as they may be faster due to knowing the type of msg rather than it being hidden
// behind an interface.
func (f *Frontend) Send(msg FrontendMessage) {
+ if f.encodeError != nil {
+ return
+ }
+
prevLen := len(f.wbuf)
- f.wbuf = msg.Encode(f.wbuf)
+ newBuf, err := msg.Encode(f.wbuf)
+ if err != nil {
+ f.encodeError = err
+ return
+ }
+ f.wbuf = newBuf
+
if f.tracer != nil {
f.tracer.traceMessage('F', int32(len(f.wbuf)-prevLen), msg)
}
@@ -81,6 +92,12 @@ func (f *Frontend) Send(msg FrontendMessage) {
// Flush writes any pending messages to the backend (i.e. the server).
func (f *Frontend) Flush() error {
+ if err := f.encodeError; err != nil {
+ f.encodeError = nil
+ f.wbuf = f.wbuf[:0]
+ return &writeError{err: err, safeToRetry: true}
+ }
+
if len(f.wbuf) == 0 {
return nil
}
@@ -116,71 +133,141 @@ func (f *Frontend) Untrace() {
f.tracer = nil
}
-// SendBind sends a Bind message to the backend (i.e. the server). The message is not guaranteed to be written until
-// Flush is called.
+// SendBind sends a Bind message to the backend (i.e. the server). The message is buffered until Flush is called. Any
+// error encountered will be returned from Flush.
func (f *Frontend) SendBind(msg *Bind) {
+ if f.encodeError != nil {
+ return
+ }
+
prevLen := len(f.wbuf)
- f.wbuf = msg.Encode(f.wbuf)
+ newBuf, err := msg.Encode(f.wbuf)
+ if err != nil {
+ f.encodeError = err
+ return
+ }
+ f.wbuf = newBuf
+
if f.tracer != nil {
f.tracer.traceBind('F', int32(len(f.wbuf)-prevLen), msg)
}
}
-// SendParse sends a Parse message to the backend (i.e. the server). The message is not guaranteed to be written until
-// Flush is called.
+// SendParse sends a Parse message to the backend (i.e. the server). The message is buffered until Flush is called. Any
+// error encountered will be returned from Flush.
func (f *Frontend) SendParse(msg *Parse) {
+ if f.encodeError != nil {
+ return
+ }
+
prevLen := len(f.wbuf)
- f.wbuf = msg.Encode(f.wbuf)
+ newBuf, err := msg.Encode(f.wbuf)
+ if err != nil {
+ f.encodeError = err
+ return
+ }
+ f.wbuf = newBuf
+
if f.tracer != nil {
f.tracer.traceParse('F', int32(len(f.wbuf)-prevLen), msg)
}
}
-// SendClose sends a Close message to the backend (i.e. the server). The message is not guaranteed to be written until
-// Flush is called.
+// SendClose sends a Close message to the backend (i.e. the server). The message is buffered until Flush is called. Any
+// error encountered will be returned from Flush.
func (f *Frontend) SendClose(msg *Close) {
+ if f.encodeError != nil {
+ return
+ }
+
prevLen := len(f.wbuf)
- f.wbuf = msg.Encode(f.wbuf)
+ newBuf, err := msg.Encode(f.wbuf)
+ if err != nil {
+ f.encodeError = err
+ return
+ }
+ f.wbuf = newBuf
+
if f.tracer != nil {
f.tracer.traceClose('F', int32(len(f.wbuf)-prevLen), msg)
}
}
-// SendDescribe sends a Describe message to the backend (i.e. the server). The message is not guaranteed to be written until
-// Flush is called.
+// SendDescribe sends a Describe message to the backend (i.e. the server). The message is buffered until Flush is
+// called. Any error encountered will be returned from Flush.
func (f *Frontend) SendDescribe(msg *Describe) {
+ if f.encodeError != nil {
+ return
+ }
+
prevLen := len(f.wbuf)
- f.wbuf = msg.Encode(f.wbuf)
+ newBuf, err := msg.Encode(f.wbuf)
+ if err != nil {
+ f.encodeError = err
+ return
+ }
+ f.wbuf = newBuf
+
if f.tracer != nil {
f.tracer.traceDescribe('F', int32(len(f.wbuf)-prevLen), msg)
}
}
-// SendExecute sends an Execute message to the backend (i.e. the server). The message is not guaranteed to be written until
-// Flush is called.
+// SendExecute sends an Execute message to the backend (i.e. the server). The message is buffered until Flush is called.
+// Any error encountered will be returned from Flush.
func (f *Frontend) SendExecute(msg *Execute) {
+ if f.encodeError != nil {
+ return
+ }
+
prevLen := len(f.wbuf)
- f.wbuf = msg.Encode(f.wbuf)
+ newBuf, err := msg.Encode(f.wbuf)
+ if err != nil {
+ f.encodeError = err
+ return
+ }
+ f.wbuf = newBuf
+
if f.tracer != nil {
f.tracer.TraceQueryute('F', int32(len(f.wbuf)-prevLen), msg)
}
}
-// SendSync sends a Sync message to the backend (i.e. the server). The message is not guaranteed to be written until
-// Flush is called.
+// SendSync sends a Sync message to the backend (i.e. the server). The message is buffered until Flush is called. Any
+// error encountered will be returned from Flush.
func (f *Frontend) SendSync(msg *Sync) {
+ if f.encodeError != nil {
+ return
+ }
+
prevLen := len(f.wbuf)
- f.wbuf = msg.Encode(f.wbuf)
+ newBuf, err := msg.Encode(f.wbuf)
+ if err != nil {
+ f.encodeError = err
+ return
+ }
+ f.wbuf = newBuf
+
if f.tracer != nil {
f.tracer.traceSync('F', int32(len(f.wbuf)-prevLen), msg)
}
}
-// SendQuery sends a Query message to the backend (i.e. the server). The message is not guaranteed to be written until
-// Flush is called.
+// SendQuery sends a Query message to the backend (i.e. the server). The message is buffered until Flush is called. Any
+// error encountered will be returned from Flush.
func (f *Frontend) SendQuery(msg *Query) {
+ if f.encodeError != nil {
+ return
+ }
+
prevLen := len(f.wbuf)
- f.wbuf = msg.Encode(f.wbuf)
+ newBuf, err := msg.Encode(f.wbuf)
+ if err != nil {
+ f.encodeError = err
+ return
+ }
+ f.wbuf = newBuf
+
if f.tracer != nil {
f.tracer.traceQuery('F', int32(len(f.wbuf)-prevLen), msg)
}