mirror of
https://github.com/jackc/pgx.git
synced 2025-05-31 11:42:24 +00:00
Use extended query builder everywhere
This commit is contained in:
parent
c418d45f75
commit
b0dac84d77
107
conn.go
107
conn.go
@ -2,9 +2,6 @@ package pgx
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql/driver"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -393,6 +390,7 @@ func (c *Conn) Exec(ctx context.Context, sql string, arguments ...interface{}) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) {
|
func (c *Conn) exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) {
|
||||||
|
c.eqb.Reset()
|
||||||
|
|
||||||
if ps, ok := c.preparedStatements[sql]; ok {
|
if ps, ok := c.preparedStatements[sql]; ok {
|
||||||
args, err := convertDriverValuers(arguments)
|
args, err := convertDriverValuers(arguments)
|
||||||
@ -400,28 +398,24 @@ func (c *Conn) exec(ctx context.Context, sql string, arguments ...interface{}) (
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
paramFormats := make([]int16, len(args))
|
|
||||||
paramValues := make([][]byte, len(args))
|
|
||||||
for i := range args {
|
for i := range args {
|
||||||
paramFormats[i] = chooseParameterFormatCode(c.ConnInfo, ps.ParameterOIDs[i], args[i])
|
err = c.eqb.AppendParam(c.ConnInfo, ps.ParameterOIDs[i], args[i])
|
||||||
paramValues[i], err = newencodePreparedStatementArgument(c.ConnInfo, ps.ParameterOIDs[i], args[i])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultFormats := make([]int16, len(ps.FieldDescriptions))
|
for i := range ps.FieldDescriptions {
|
||||||
for i := range resultFormats {
|
|
||||||
if dt, ok := c.ConnInfo.DataTypeForOID(pgtype.OID(ps.FieldDescriptions[i].DataTypeOID)); ok {
|
if dt, ok := c.ConnInfo.DataTypeForOID(pgtype.OID(ps.FieldDescriptions[i].DataTypeOID)); ok {
|
||||||
if _, ok := dt.Value.(pgtype.BinaryDecoder); ok {
|
if _, ok := dt.Value.(pgtype.BinaryDecoder); ok {
|
||||||
resultFormats[i] = BinaryFormatCode
|
c.eqb.AppendResultFormat(BinaryFormatCode)
|
||||||
} else {
|
} else {
|
||||||
resultFormats[i] = TextFormatCode
|
c.eqb.AppendResultFormat(TextFormatCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := c.pgConn.ExecPrepared(ctx, ps.Name, paramValues, paramFormats, resultFormats).Read()
|
result := c.pgConn.ExecPrepared(ctx, ps.Name, c.eqb.paramValues, c.eqb.paramFormats, c.eqb.resultFormats).Read()
|
||||||
return result.CommandTag, result.Err
|
return result.CommandTag, result.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,87 +455,29 @@ func (c *Conn) exec(ctx context.Context, sql string, arguments ...interface{}) (
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
paramFormats := make([]int16, len(arguments))
|
|
||||||
paramValues := make([][]byte, len(arguments))
|
|
||||||
for i := range arguments {
|
for i := range arguments {
|
||||||
paramFormats[i] = chooseParameterFormatCode(c.ConnInfo, ps.ParameterOIDs[i], arguments[i])
|
err = c.eqb.AppendParam(c.ConnInfo, ps.ParameterOIDs[i], arguments[i])
|
||||||
paramValues[i], err = newencodePreparedStatementArgument(c.ConnInfo, ps.ParameterOIDs[i], arguments[i])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resultFormats := make([]int16, len(ps.FieldDescriptions))
|
for i := range ps.FieldDescriptions {
|
||||||
for i := range resultFormats {
|
|
||||||
if dt, ok := c.ConnInfo.DataTypeForOID(pgtype.OID(ps.FieldDescriptions[i].DataTypeOID)); ok {
|
if dt, ok := c.ConnInfo.DataTypeForOID(pgtype.OID(ps.FieldDescriptions[i].DataTypeOID)); ok {
|
||||||
if _, ok := dt.Value.(pgtype.BinaryDecoder); ok {
|
if _, ok := dt.Value.(pgtype.BinaryDecoder); ok {
|
||||||
resultFormats[i] = BinaryFormatCode
|
c.eqb.AppendResultFormat(BinaryFormatCode)
|
||||||
} else {
|
} else {
|
||||||
resultFormats[i] = TextFormatCode
|
c.eqb.AppendResultFormat(TextFormatCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := c.pgConn.ExecPrepared(ctx, psd.Name, paramValues, paramFormats, resultFormats).Read()
|
result := c.pgConn.ExecPrepared(ctx, psd.Name, c.eqb.paramValues, c.eqb.paramFormats, c.eqb.resultFormats).Read()
|
||||||
return result.CommandTag, result.Err
|
return result.CommandTag, result.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newencodePreparedStatementArgument(ci *pgtype.ConnInfo, oid pgtype.OID, arg interface{}) ([]byte, error) {
|
|
||||||
if arg == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - don't allocate a new buf for each encoded prepared statement. The empty slice is necessary because otherwise empty strings may be encoded as []byte(nil) instead of []byte{}
|
|
||||||
buf := make([]byte, 0)
|
|
||||||
|
|
||||||
switch arg := arg.(type) {
|
|
||||||
case pgtype.BinaryEncoder:
|
|
||||||
return arg.EncodeBinary(ci, buf)
|
|
||||||
case pgtype.TextEncoder:
|
|
||||||
return arg.EncodeText(ci, buf)
|
|
||||||
case string:
|
|
||||||
return []byte(arg), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
refVal := reflect.ValueOf(arg)
|
|
||||||
|
|
||||||
if refVal.Kind() == reflect.Ptr {
|
|
||||||
if refVal.IsNil() {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
arg = refVal.Elem().Interface()
|
|
||||||
return newencodePreparedStatementArgument(ci, oid, arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
if dt, ok := ci.DataTypeForOID(oid); ok {
|
|
||||||
value := dt.Value
|
|
||||||
err := value.Set(arg)
|
|
||||||
if err != nil {
|
|
||||||
{
|
|
||||||
if arg, ok := arg.(driver.Valuer); ok {
|
|
||||||
v, err := callValuerValue(arg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return newencodePreparedStatementArgument(ci, oid, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return value.(pgtype.BinaryEncoder).EncodeBinary(ci, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
if strippedArg, ok := stripNamedType(&refVal); ok {
|
|
||||||
return newencodePreparedStatementArgument(ci, oid, strippedArg)
|
|
||||||
}
|
|
||||||
return nil, SerializationError(fmt.Sprintf("Cannot encode %T into oid %v - %T must implement Encoder or be converted to a string", arg, oid, arg))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) getRows(sql string, args []interface{}) *connRows {
|
func (c *Conn) getRows(sql string, args []interface{}) *connRows {
|
||||||
if len(c.preallocatedRows) == 0 {
|
if len(c.preallocatedRows) == 0 {
|
||||||
c.preallocatedRows = make([]connRows, 64)
|
c.preallocatedRows = make([]connRows, 64)
|
||||||
@ -669,6 +605,8 @@ func (c *Conn) SendBatch(ctx context.Context, b *Batch) BatchResults {
|
|||||||
batch := &pgconn.Batch{}
|
batch := &pgconn.Batch{}
|
||||||
|
|
||||||
for _, bi := range b.items {
|
for _, bi := range b.items {
|
||||||
|
c.eqb.Reset()
|
||||||
|
|
||||||
var parameterOIDs []pgtype.OID
|
var parameterOIDs []pgtype.OID
|
||||||
ps := c.preparedStatements[bi.query]
|
ps := c.preparedStatements[bi.query]
|
||||||
|
|
||||||
@ -683,11 +621,8 @@ func (c *Conn) SendBatch(ctx context.Context, b *Batch) BatchResults {
|
|||||||
return &batchResults{err: err}
|
return &batchResults{err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
paramFormats := make([]int16, len(args))
|
|
||||||
paramValues := make([][]byte, len(args))
|
|
||||||
for i := range args {
|
for i := range args {
|
||||||
paramFormats[i] = chooseParameterFormatCode(c.ConnInfo, parameterOIDs[i], args[i])
|
err = c.eqb.AppendParam(c.ConnInfo, parameterOIDs[i], args[i])
|
||||||
paramValues[i], err = newencodePreparedStatementArgument(c.ConnInfo, parameterOIDs[i], args[i])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &batchResults{err: err}
|
return &batchResults{err: err}
|
||||||
}
|
}
|
||||||
@ -697,25 +632,27 @@ func (c *Conn) SendBatch(ctx context.Context, b *Batch) BatchResults {
|
|||||||
if ps != nil {
|
if ps != nil {
|
||||||
resultFormats := bi.resultFormatCodes
|
resultFormats := bi.resultFormatCodes
|
||||||
if resultFormats == nil {
|
if resultFormats == nil {
|
||||||
resultFormats = make([]int16, len(ps.FieldDescriptions))
|
|
||||||
for i := range resultFormats {
|
for i := range ps.FieldDescriptions {
|
||||||
if dt, ok := c.ConnInfo.DataTypeForOID(pgtype.OID(ps.FieldDescriptions[i].DataTypeOID)); ok {
|
if dt, ok := c.ConnInfo.DataTypeForOID(pgtype.OID(ps.FieldDescriptions[i].DataTypeOID)); ok {
|
||||||
if _, ok := dt.Value.(pgtype.BinaryDecoder); ok {
|
if _, ok := dt.Value.(pgtype.BinaryDecoder); ok {
|
||||||
resultFormats[i] = BinaryFormatCode
|
c.eqb.AppendResultFormat(BinaryFormatCode)
|
||||||
} else {
|
} else {
|
||||||
resultFormats[i] = TextFormatCode
|
c.eqb.AppendResultFormat(TextFormatCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resultFormats = c.eqb.resultFormats
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.ExecPrepared(ps.Name, paramValues, paramFormats, resultFormats)
|
batch.ExecPrepared(ps.Name, c.eqb.paramValues, c.eqb.paramFormats, resultFormats)
|
||||||
} else {
|
} else {
|
||||||
oids := make([]uint32, len(parameterOIDs))
|
oids := make([]uint32, len(parameterOIDs))
|
||||||
for i := 0; i < len(parameterOIDs); i++ {
|
for i := 0; i < len(parameterOIDs); i++ {
|
||||||
oids[i] = uint32(parameterOIDs[i])
|
oids[i] = uint32(parameterOIDs[i])
|
||||||
}
|
}
|
||||||
batch.ExecParams(bi.query, paramValues, oids, paramFormats, bi.resultFormatCodes)
|
batch.ExecParams(bi.query, c.eqb.paramValues, oids, c.eqb.paramFormats, bi.resultFormatCodes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user