2
0
Files
pgx/batch.go
T
Jack Christensen 6972a57421 pgtype.OID type should only be used for scanning and encoding values
It was a mistake to use it in other contexts. This made interop
difficult between pacakges that depended on pgtype such as pgx and
packages that did not like pgconn and pgproto3. In particular this was
awkward for prepared statements.

This is preparation for removing pgx.PreparedStatement in favor of
pgconn.PreparedStatement.
2019-08-24 13:55:57 -05:00

113 lines
3.2 KiB
Go

package pgx
import (
"context"
"github.com/jackc/pgconn"
errors "golang.org/x/xerrors"
)
type batchItem struct {
query string
arguments []interface{}
parameterOIDs []uint32
resultFormatCodes []int16
}
// Batch queries are a way of bundling multiple queries together to avoid
// unnecessary network round trips.
type Batch struct {
items []*batchItem
}
// Queue queues a query to batch b. query can be an SQL query or the name of a prepared statement. parameterOIDs and
// resultFormatCodes should be nil if query is a prepared statement. Otherwise, parameterOIDs are required if there are
// parameters and resultFormatCodes are required if there is a result.
func (b *Batch) Queue(query string, arguments []interface{}, parameterOIDs []uint32, resultFormatCodes []int16) {
b.items = append(b.items, &batchItem{
query: query,
arguments: arguments,
parameterOIDs: parameterOIDs,
resultFormatCodes: resultFormatCodes,
})
}
type BatchResults interface {
// ExecResults reads the results from the next query in the batch as if the query has been sent with Exec.
ExecResults() (pgconn.CommandTag, error)
// QueryResults reads the results from the next query in the batch as if the query has been sent with Query.
QueryResults() (Rows, error)
// QueryRowResults reads the results from the next query in the batch as if the query has been sent with QueryRow.
QueryRowResults() Row
// Close closes the batch operation. Any error that occured during a batch operation may have made it impossible to
// resyncronize the connection with the server. In this case the underlying connection will have been closed.
Close() error
}
type batchResults struct {
ctx context.Context
conn *Conn
mrr *pgconn.MultiResultReader
err error
}
// ExecResults reads the results from the next query in the batch as if the query has been sent with Exec.
func (br *batchResults) ExecResults() (pgconn.CommandTag, error) {
if br.err != nil {
return nil, br.err
}
if !br.mrr.NextResult() {
err := br.mrr.Close()
if err == nil {
err = errors.New("no result")
}
return nil, err
}
return br.mrr.ResultReader().Close()
}
// QueryResults reads the results from the next query in the batch as if the query has been sent with Query.
func (br *batchResults) QueryResults() (Rows, error) {
rows := br.conn.getRows(br.ctx, "batch query", nil)
if br.err != nil {
rows.err = br.err
rows.closed = true
return rows, br.err
}
if !br.mrr.NextResult() {
rows.err = br.mrr.Close()
if rows.err == nil {
rows.err = errors.New("no result")
}
rows.closed = true
return rows, rows.err
}
rows.resultReader = br.mrr.ResultReader()
return rows, nil
}
// QueryRowResults reads the results from the next query in the batch as if the query has been sent with QueryRow.
func (br *batchResults) QueryRowResults() Row {
rows, _ := br.QueryResults()
return (*connRow)(rows.(*connRows))
}
// Close closes the batch operation. Any error that occured during a batch operation may have made it impossible to
// resyncronize the connection with the server. In this case the underlying connection will have been closed.
func (br *batchResults) Close() error {
if br.err != nil {
return br.err
}
return br.mrr.Close()
}