6972a57421
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.
113 lines
3.2 KiB
Go
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()
|
|
}
|