mirror of https://github.com/jackc/pgx.git
Add deallocate to pipeline mode
parent
1168b375e4
commit
a86f4f3db9
|
@ -1677,6 +1677,9 @@ type Pipeline struct {
|
||||||
// PipelineSync is returned by GetResults when a ReadyForQuery message is received.
|
// PipelineSync is returned by GetResults when a ReadyForQuery message is received.
|
||||||
type PipelineSync struct{}
|
type PipelineSync struct{}
|
||||||
|
|
||||||
|
// CloseComplete is returned by GetResults when a CloseComplete message is received.
|
||||||
|
type CloseComplete struct{}
|
||||||
|
|
||||||
// StartPipeline switches the connection to pipeline mode and returns a *Pipeline. In pipeline mode requests can be sent
|
// StartPipeline switches the connection to pipeline mode and returns a *Pipeline. In pipeline mode requests can be sent
|
||||||
// to the server without waiting for a response. Close must be called on the returned *Pipeline to return the connection
|
// to the server without waiting for a response. Close must be called on the returned *Pipeline to return the connection
|
||||||
// to normal mode. While in pipeline mode, no methods that communicate with the server may be called except
|
// to normal mode. While in pipeline mode, no methods that communicate with the server may be called except
|
||||||
|
@ -1723,6 +1726,16 @@ func (p *Pipeline) SendPrepare(name, sql string, paramOIDs []uint32) {
|
||||||
p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'S', Name: name})
|
p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'S', Name: name})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendDeallocate deallocates a prepared statement.
|
||||||
|
func (p *Pipeline) SendDeallocate(name string) {
|
||||||
|
if p.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.pendingSync = true
|
||||||
|
|
||||||
|
p.conn.frontend.SendClose(&pgproto3.Close{ObjectType: 'S', Name: name})
|
||||||
|
}
|
||||||
|
|
||||||
// SendQueryParams is the pipeline version of *PgConn.QueryParams.
|
// SendQueryParams is the pipeline version of *PgConn.QueryParams.
|
||||||
func (p *Pipeline) SendQueryParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) {
|
func (p *Pipeline) SendQueryParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) {
|
||||||
if p.closed {
|
if p.closed {
|
||||||
|
@ -1825,6 +1838,8 @@ func (p *Pipeline) GetResults() (results any, err error) {
|
||||||
if _, ok := peekedMsg.(*pgproto3.ParameterDescription); ok {
|
if _, ok := peekedMsg.(*pgproto3.ParameterDescription); ok {
|
||||||
return p.getResultsPrepare()
|
return p.getResultsPrepare()
|
||||||
}
|
}
|
||||||
|
case *pgproto3.CloseComplete:
|
||||||
|
return &CloseComplete{}, nil
|
||||||
case *pgproto3.ReadyForQuery:
|
case *pgproto3.ReadyForQuery:
|
||||||
p.expectedReadyForQueryCount--
|
p.expectedReadyForQueryCount--
|
||||||
return &PipelineSync{}, nil
|
return &PipelineSync{}, nil
|
||||||
|
|
|
@ -2190,6 +2190,47 @@ func TestPipelinePrepareError(t *testing.T) {
|
||||||
ensureConnValid(t, pgConn)
|
ensureConnValid(t, pgConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPipelinePrepareAndDeallocate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
pgConn, err := pgconn.Connect(context.Background(), os.Getenv("PGX_TEST_CONN_STRING"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer closeConn(t, pgConn)
|
||||||
|
|
||||||
|
pipeline := pgConn.StartPipeline(context.Background())
|
||||||
|
pipeline.SendPrepare("selectInt", "select $1::bigint as a", nil)
|
||||||
|
pipeline.SendDeallocate("selectInt")
|
||||||
|
err = pipeline.Sync()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
results, err := pipeline.GetResults()
|
||||||
|
require.NoError(t, err)
|
||||||
|
sd, ok := results.(*pgconn.StatementDescription)
|
||||||
|
require.Truef(t, ok, "expected StatementDescription, got: %#v", results)
|
||||||
|
require.Len(t, sd.Fields, 1)
|
||||||
|
require.Equal(t, string(sd.Fields[0].Name), "a")
|
||||||
|
require.Equal(t, []uint32{pgtype.Int8OID}, sd.ParamOIDs)
|
||||||
|
|
||||||
|
results, err = pipeline.GetResults()
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, ok = results.(*pgconn.CloseComplete)
|
||||||
|
require.Truef(t, ok, "expected CloseComplete, got: %#v", results)
|
||||||
|
|
||||||
|
results, err = pipeline.GetResults()
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, ok = results.(*pgconn.PipelineSync)
|
||||||
|
require.Truef(t, ok, "expected PipelineSync, got: %#v", results)
|
||||||
|
|
||||||
|
results, err = pipeline.GetResults()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Nil(t, results)
|
||||||
|
|
||||||
|
err = pipeline.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ensureConnValid(t, pgConn)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPipelineQuery(t *testing.T) {
|
func TestPipelineQuery(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,16 @@ func (f *Frontend) SendParse(msg *Parse) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendClose sends a Close message to the backend (i.e. the server). The message is not guaranteed to be written until
|
||||||
|
// Flush is called.
|
||||||
|
func (f *Frontend) SendClose(msg *Close) {
|
||||||
|
prevLen := len(f.wbuf)
|
||||||
|
f.wbuf = msg.Encode(f.wbuf)
|
||||||
|
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
|
// SendDescribe sends a Describe message to the backend (i.e. the server). The message is not guaranteed to be written until
|
||||||
// Flush is called.
|
// Flush is called.
|
||||||
func (f *Frontend) SendDescribe(msg *Describe) {
|
func (f *Frontend) SendDescribe(msg *Describe) {
|
||||||
|
|
Loading…
Reference in New Issue