...
|
...
|
@@ -19,6 +19,7 @@ import ( |
|
|
"github.com/go-pg/pg/v10/types"
|
|
|
)
|
|
|
|
|
|
// https://www.postgresql.org/docs/current/protocol-message-formats.html
|
|
|
const (
|
|
|
commandCompleteMsg = 'C'
|
|
|
errorResponseMsg = 'E'
|
...
|
...
|
@@ -84,7 +85,7 @@ func (db *baseDB) startup( |
|
|
return err
|
|
|
}
|
|
|
|
|
|
return cn.WithReader(c, db.opt.ReadTimeout, func(rd *pool.BufReader) error {
|
|
|
return cn.WithReader(c, db.opt.ReadTimeout, func(rd *pool.ReaderContext) error {
|
|
|
for {
|
|
|
typ, msgLen, err := readMessageType(rd)
|
|
|
if err != nil {
|
...
|
...
|
@@ -137,7 +138,7 @@ func (db *baseDB) enableSSL(c context.Context, cn *pool.Conn, tlsConf *tls.Confi |
|
|
return err
|
|
|
}
|
|
|
|
|
|
err = cn.WithReader(c, db.opt.ReadTimeout, func(rd *pool.BufReader) error {
|
|
|
err = cn.WithReader(c, db.opt.ReadTimeout, func(rd *pool.ReaderContext) error {
|
|
|
c, err := rd.ReadByte()
|
|
|
if err != nil {
|
|
|
return err
|
...
|
...
|
@@ -156,7 +157,7 @@ func (db *baseDB) enableSSL(c context.Context, cn *pool.Conn, tlsConf *tls.Confi |
|
|
}
|
|
|
|
|
|
func (db *baseDB) auth(
|
|
|
c context.Context, cn *pool.Conn, rd *pool.BufReader, user, password string,
|
|
|
c context.Context, cn *pool.Conn, rd *pool.ReaderContext, user, password string,
|
|
|
) error {
|
|
|
num, err := readInt32(rd)
|
|
|
if err != nil {
|
...
|
...
|
@@ -178,7 +179,7 @@ func (db *baseDB) auth( |
|
|
}
|
|
|
|
|
|
func (db *baseDB) authCleartext(
|
|
|
c context.Context, cn *pool.Conn, rd *pool.BufReader, password string,
|
|
|
c context.Context, cn *pool.Conn, rd *pool.ReaderContext, password string,
|
|
|
) error {
|
|
|
err := cn.WithWriter(c, db.opt.WriteTimeout, func(wb *pool.WriteBuffer) error {
|
|
|
writePasswordMsg(wb, password)
|
...
|
...
|
@@ -191,7 +192,7 @@ func (db *baseDB) authCleartext( |
|
|
}
|
|
|
|
|
|
func (db *baseDB) authMD5(
|
|
|
c context.Context, cn *pool.Conn, rd *pool.BufReader, user, password string,
|
|
|
c context.Context, cn *pool.Conn, rd *pool.ReaderContext, user, password string,
|
|
|
) error {
|
|
|
b, err := rd.ReadN(4)
|
|
|
if err != nil {
|
...
|
...
|
@@ -210,7 +211,7 @@ func (db *baseDB) authMD5( |
|
|
return readAuthOK(rd)
|
|
|
}
|
|
|
|
|
|
func readAuthOK(rd *pool.BufReader) error {
|
|
|
func readAuthOK(rd *pool.ReaderContext) error {
|
|
|
c, _, err := readMessageType(rd)
|
|
|
if err != nil {
|
|
|
return err
|
...
|
...
|
@@ -238,7 +239,7 @@ func readAuthOK(rd *pool.BufReader) error { |
|
|
}
|
|
|
|
|
|
func (db *baseDB) authSASL(
|
|
|
c context.Context, cn *pool.Conn, rd *pool.BufReader, user, password string,
|
|
|
c context.Context, cn *pool.Conn, rd *pool.ReaderContext, user, password string,
|
|
|
) error {
|
|
|
s, err := readString(rd)
|
|
|
if err != nil {
|
...
|
...
|
@@ -332,7 +333,7 @@ func (db *baseDB) authSASL( |
|
|
}
|
|
|
}
|
|
|
|
|
|
func readAuthSASLFinal(rd *pool.BufReader, client *sasl.Negotiator) error {
|
|
|
func readAuthSASLFinal(rd *pool.ReaderContext, client *sasl.Negotiator) error {
|
|
|
c, n, err := readMessageType(rd)
|
|
|
if err != nil {
|
|
|
return err
|
...
|
...
|
@@ -485,8 +486,8 @@ func writeParseDescribeSyncMsg(buf *pool.WriteBuffer, name, q string) { |
|
|
writeSyncMsg(buf)
|
|
|
}
|
|
|
|
|
|
func readParseDescribeSync(rd *pool.BufReader) ([][]byte, error) {
|
|
|
var columns [][]byte
|
|
|
func readParseDescribeSync(rd *pool.ReaderContext) ([]types.ColumnInfo, error) {
|
|
|
var columns []types.ColumnInfo
|
|
|
var firstErr error
|
|
|
for {
|
|
|
c, msgLen, err := readMessageType(rd)
|
...
|
...
|
@@ -500,7 +501,7 @@ func readParseDescribeSync(rd *pool.BufReader) ([][]byte, error) { |
|
|
return nil, err
|
|
|
}
|
|
|
case rowDescriptionMsg: // Response to the DESCRIBE message.
|
|
|
columns, err = readRowDescription(rd, nil)
|
|
|
columns, err = readRowDescription(rd, pool.NewColumnAlloc())
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
...
|
...
|
@@ -582,7 +583,7 @@ func writeCloseMsg(buf *pool.WriteBuffer, name string) { |
|
|
buf.FinishMessage()
|
|
|
}
|
|
|
|
|
|
func readCloseCompleteMsg(rd *pool.BufReader) error {
|
|
|
func readCloseCompleteMsg(rd *pool.ReaderContext) error {
|
|
|
for {
|
|
|
c, msgLen, err := readMessageType(rd)
|
|
|
if err != nil {
|
...
|
...
|
@@ -612,7 +613,7 @@ func readCloseCompleteMsg(rd *pool.BufReader) error { |
|
|
}
|
|
|
}
|
|
|
|
|
|
func readSimpleQuery(rd *pool.BufReader) (*result, error) {
|
|
|
func readSimpleQuery(rd *pool.ReaderContext) (*result, error) {
|
|
|
var res result
|
|
|
var firstErr error
|
|
|
for {
|
...
|
...
|
@@ -675,7 +676,7 @@ func readSimpleQuery(rd *pool.BufReader) (*result, error) { |
|
|
}
|
|
|
}
|
|
|
|
|
|
func readExtQuery(rd *pool.BufReader) (*result, error) {
|
|
|
func readExtQuery(rd *pool.ReaderContext) (*result, error) {
|
|
|
var res result
|
|
|
var firstErr error
|
|
|
for {
|
...
|
...
|
@@ -739,42 +740,47 @@ func readExtQuery(rd *pool.BufReader) (*result, error) { |
|
|
}
|
|
|
}
|
|
|
|
|
|
func readRowDescription(rd *pool.BufReader, columns [][]byte) ([][]byte, error) {
|
|
|
colNum, err := readInt16(rd)
|
|
|
func readRowDescription(
|
|
|
rd *pool.ReaderContext, columnAlloc *pool.ColumnAlloc,
|
|
|
) ([]types.ColumnInfo, error) {
|
|
|
numCol, err := readInt16(rd)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
columns = setByteSliceLen(columns, int(colNum))
|
|
|
for i := 0; i < int(colNum); i++ {
|
|
|
for i := 0; i < int(numCol); i++ {
|
|
|
b, err := rd.ReadSlice(0)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
columns[i] = append(columns[i][:0], b[:len(b)-1]...)
|
|
|
|
|
|
_, err = rd.ReadN(18)
|
|
|
if err != nil {
|
|
|
col := columnAlloc.New(int16(i), b[:len(b)-1])
|
|
|
|
|
|
if _, err := rd.ReadN(6); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return columns, nil
|
|
|
}
|
|
|
dataType, err := readInt32(rd)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
col.DataType = dataType
|
|
|
|
|
|
func setByteSliceLen(b [][]byte, n int) [][]byte {
|
|
|
if n <= cap(b) {
|
|
|
return b[:n]
|
|
|
if _, err := rd.ReadN(8); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
}
|
|
|
b = b[:cap(b)]
|
|
|
b = append(b, make([][]byte, n-cap(b))...)
|
|
|
return b
|
|
|
|
|
|
return columnAlloc.Columns(), nil
|
|
|
}
|
|
|
|
|
|
func readDataRow(
|
|
|
ctx context.Context, rd *pool.BufReader, scanner orm.ColumnScanner, columns [][]byte,
|
|
|
ctx context.Context,
|
|
|
rd *pool.ReaderContext,
|
|
|
columns []types.ColumnInfo,
|
|
|
scanner orm.ColumnScanner,
|
|
|
) error {
|
|
|
colNum, err := readInt16(rd)
|
|
|
numCol, err := readInt16(rd)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
...
|
...
|
@@ -787,35 +793,28 @@ func readDataRow( |
|
|
|
|
|
var firstErr error
|
|
|
|
|
|
for colIdx := int16(0); colIdx < colNum; colIdx++ {
|
|
|
for colIdx := int16(0); colIdx < numCol; colIdx++ {
|
|
|
n, err := readInt32(rd)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
column := internal.BytesToString(columns[colIdx])
|
|
|
var colRd types.Reader
|
|
|
if n >= 0 {
|
|
|
bytesRd := rd.BytesReader(int(n))
|
|
|
if bytesRd != nil {
|
|
|
colRd = bytesRd
|
|
|
} else {
|
|
|
rd.SetAvailable(int(n))
|
|
|
colRd = rd
|
|
|
}
|
|
|
if int(n) <= rd.Buffered() {
|
|
|
colRd = rd.BytesReader(int(n))
|
|
|
} else {
|
|
|
colRd = rd.BytesReader(0)
|
|
|
rd.SetAvailable(int(n))
|
|
|
colRd = rd
|
|
|
}
|
|
|
|
|
|
err = scanner.ScanColumn(int(colIdx), column, colRd, int(n))
|
|
|
if err != nil && firstErr == nil {
|
|
|
column := columns[colIdx]
|
|
|
if err := scanner.ScanColumn(column, colRd, int(n)); err != nil && firstErr == nil {
|
|
|
firstErr = internal.Errorf(err.Error())
|
|
|
}
|
|
|
|
|
|
if rd == colRd {
|
|
|
if rd.Available() > 0 {
|
|
|
_, err = rd.Discard(rd.Available())
|
|
|
if err != nil && firstErr == nil {
|
|
|
if _, err := rd.Discard(rd.Available()); err != nil && firstErr == nil {
|
|
|
firstErr = err
|
|
|
}
|
|
|
}
|
...
|
...
|
@@ -841,8 +840,9 @@ func newModel(mod interface{}) (orm.Model, error) { |
|
|
}
|
|
|
|
|
|
func readSimpleQueryData(
|
|
|
ctx context.Context, rd *pool.BufReader, mod interface{},
|
|
|
ctx context.Context, rd *pool.ReaderContext, mod interface{},
|
|
|
) (*result, error) {
|
|
|
var columns []types.ColumnInfo
|
|
|
var res result
|
|
|
var firstErr error
|
|
|
for {
|
...
|
...
|
@@ -853,7 +853,7 @@ func readSimpleQueryData( |
|
|
|
|
|
switch c {
|
|
|
case rowDescriptionMsg:
|
|
|
rd.Columns, err = readRowDescription(rd, rd.Columns[:0])
|
|
|
columns, err = readRowDescription(rd, rd.ColumnAlloc)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
...
|
...
|
@@ -870,7 +870,7 @@ func readSimpleQueryData( |
|
|
}
|
|
|
case dataRowMsg:
|
|
|
scanner := res.model.NextColumnScanner()
|
|
|
if err := readDataRow(ctx, rd, scanner, rd.Columns); err != nil {
|
|
|
if err := readDataRow(ctx, rd, columns, scanner); err != nil {
|
|
|
if firstErr == nil {
|
|
|
firstErr = err
|
|
|
}
|
...
|
...
|
@@ -925,7 +925,7 @@ func readSimpleQueryData( |
|
|
}
|
|
|
|
|
|
func readExtQueryData(
|
|
|
ctx context.Context, rd *pool.BufReader, mod interface{}, columns [][]byte,
|
|
|
ctx context.Context, rd *pool.ReaderContext, mod interface{}, columns []types.ColumnInfo,
|
|
|
) (*result, error) {
|
|
|
var res result
|
|
|
var firstErr error
|
...
|
...
|
@@ -954,7 +954,7 @@ func readExtQueryData( |
|
|
}
|
|
|
|
|
|
scanner := res.model.NextColumnScanner()
|
|
|
if err := readDataRow(ctx, rd, scanner, columns); err != nil {
|
|
|
if err := readDataRow(ctx, rd, columns, scanner); err != nil {
|
|
|
if firstErr == nil {
|
|
|
firstErr = err
|
|
|
}
|
...
|
...
|
@@ -1004,7 +1004,7 @@ func readExtQueryData( |
|
|
}
|
|
|
}
|
|
|
|
|
|
func readCopyInResponse(rd *pool.BufReader) error {
|
|
|
func readCopyInResponse(rd *pool.ReaderContext) error {
|
|
|
var firstErr error
|
|
|
for {
|
|
|
c, msgLen, err := readMessageType(rd)
|
...
|
...
|
@@ -1044,7 +1044,7 @@ func readCopyInResponse(rd *pool.BufReader) error { |
|
|
}
|
|
|
}
|
|
|
|
|
|
func readCopyOutResponse(rd *pool.BufReader) error {
|
|
|
func readCopyOutResponse(rd *pool.ReaderContext) error {
|
|
|
var firstErr error
|
|
|
for {
|
|
|
c, msgLen, err := readMessageType(rd)
|
...
|
...
|
@@ -1084,7 +1084,7 @@ func readCopyOutResponse(rd *pool.BufReader) error { |
|
|
}
|
|
|
}
|
|
|
|
|
|
func readCopyData(rd *pool.BufReader, w io.Writer) (*result, error) {
|
|
|
func readCopyData(rd *pool.ReaderContext, w io.Writer) (*result, error) {
|
|
|
var res result
|
|
|
var firstErr error
|
|
|
for {
|
...
|
...
|
@@ -1162,7 +1162,7 @@ func writeCopyDone(buf *pool.WriteBuffer) { |
|
|
buf.FinishMessage()
|
|
|
}
|
|
|
|
|
|
func readReadyForQuery(rd *pool.BufReader) (*result, error) {
|
|
|
func readReadyForQuery(rd *pool.ReaderContext) (*result, error) {
|
|
|
var res result
|
|
|
var firstErr error
|
|
|
for {
|
...
|
...
|
@@ -1211,7 +1211,7 @@ func readReadyForQuery(rd *pool.BufReader) (*result, error) { |
|
|
}
|
|
|
}
|
|
|
|
|
|
func readNotification(rd *pool.BufReader) (channel, payload string, err error) {
|
|
|
func readNotification(rd *pool.ReaderContext) (channel, payload string, err error) {
|
|
|
for {
|
|
|
c, msgLen, err := readMessageType(rd)
|
|
|
if err != nil {
|
...
|
...
|
@@ -1269,17 +1269,17 @@ func terminateConn(cn *pool.Conn) error { |
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
func logNotice(rd *pool.BufReader, msgLen int) error {
|
|
|
func logNotice(rd *pool.ReaderContext, msgLen int) error {
|
|
|
_, err := rd.ReadN(msgLen)
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
func logParameterStatus(rd *pool.BufReader, msgLen int) error {
|
|
|
func logParameterStatus(rd *pool.ReaderContext, msgLen int) error {
|
|
|
_, err := rd.ReadN(msgLen)
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
func readInt16(rd *pool.BufReader) (int16, error) {
|
|
|
func readInt16(rd *pool.ReaderContext) (int16, error) {
|
|
|
b, err := rd.ReadN(2)
|
|
|
if err != nil {
|
|
|
return 0, err
|
...
|
...
|
@@ -1287,7 +1287,7 @@ func readInt16(rd *pool.BufReader) (int16, error) { |
|
|
return int16(binary.BigEndian.Uint16(b)), nil
|
|
|
}
|
|
|
|
|
|
func readInt32(rd *pool.BufReader) (int32, error) {
|
|
|
func readInt32(rd *pool.ReaderContext) (int32, error) {
|
|
|
b, err := rd.ReadN(4)
|
|
|
if err != nil {
|
|
|
return 0, err
|
...
|
...
|
@@ -1295,7 +1295,7 @@ func readInt32(rd *pool.BufReader) (int32, error) { |
|
|
return int32(binary.BigEndian.Uint32(b)), nil
|
|
|
}
|
|
|
|
|
|
func readString(rd *pool.BufReader) (string, error) {
|
|
|
func readString(rd *pool.ReaderContext) (string, error) {
|
|
|
b, err := rd.ReadSlice(0)
|
|
|
if err != nil {
|
|
|
return "", err
|
...
|
...
|
@@ -1303,7 +1303,7 @@ func readString(rd *pool.BufReader) (string, error) { |
|
|
return string(b[:len(b)-1]), nil
|
|
|
}
|
|
|
|
|
|
func readError(rd *pool.BufReader) (error, error) {
|
|
|
func readError(rd *pool.ReaderContext) (error, error) {
|
|
|
m := make(map[byte]string)
|
|
|
for {
|
|
|
c, err := rd.ReadByte()
|
...
|
...
|
@@ -1322,7 +1322,7 @@ func readError(rd *pool.BufReader) (error, error) { |
|
|
return internal.NewPGError(m), nil
|
|
|
}
|
|
|
|
|
|
func readMessageType(rd *pool.BufReader) (byte, int, error) {
|
|
|
func readMessageType(rd *pool.ReaderContext) (byte, int, error) {
|
|
|
c, err := rd.ReadByte()
|
|
|
if err != nil {
|
|
|
return 0, 0, err
|
...
|
...
|
|