Remove ValueReader
This commit is contained in:
@@ -43,7 +43,6 @@ type Rows struct {
|
|||||||
conn *Conn
|
conn *Conn
|
||||||
mr *msgReader
|
mr *msgReader
|
||||||
fields []FieldDescription
|
fields []FieldDescription
|
||||||
vr ValueReader
|
|
||||||
rowCount int
|
rowCount int
|
||||||
columnIdx int
|
columnIdx int
|
||||||
err error
|
err error
|
||||||
@@ -114,7 +113,6 @@ func (rows *Rows) Next() bool {
|
|||||||
|
|
||||||
rows.rowCount++
|
rows.rowCount++
|
||||||
rows.columnIdx = 0
|
rows.columnIdx = 0
|
||||||
rows.vr = ValueReader{}
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
t, r, err := rows.conn.rxMsg()
|
t, r, err := rows.conn.rxMsg()
|
||||||
@@ -163,24 +161,23 @@ func (rows *Rows) Conn() *Conn {
|
|||||||
return rows.conn
|
return rows.conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rows *Rows) nextColumn() (*ValueReader, bool) {
|
func (rows *Rows) nextColumn() ([]byte, *FieldDescription, bool) {
|
||||||
if rows.closed {
|
if rows.closed {
|
||||||
return nil, false
|
return nil, nil, false
|
||||||
}
|
}
|
||||||
if len(rows.fields) <= rows.columnIdx {
|
if len(rows.fields) <= rows.columnIdx {
|
||||||
rows.Fatal(ProtocolError("No next column available"))
|
rows.Fatal(ProtocolError("No next column available"))
|
||||||
return nil, false
|
return nil, nil, false
|
||||||
}
|
|
||||||
|
|
||||||
if rows.vr.Len() > 0 {
|
|
||||||
rows.mr.readBytes(rows.vr.Len())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fd := &rows.fields[rows.columnIdx]
|
fd := &rows.fields[rows.columnIdx]
|
||||||
rows.columnIdx++
|
rows.columnIdx++
|
||||||
size := rows.mr.readInt32()
|
size := rows.mr.readInt32()
|
||||||
rows.vr = ValueReader{mr: rows.mr, fd: fd, valueBytesRemaining: size}
|
var buf []byte
|
||||||
return &rows.vr, true
|
if size >= 0 {
|
||||||
|
buf = rows.mr.readBytes(size)
|
||||||
|
}
|
||||||
|
return buf, fd, true
|
||||||
}
|
}
|
||||||
|
|
||||||
type scanArgError struct {
|
type scanArgError struct {
|
||||||
@@ -204,49 +201,49 @@ func (rows *Rows) Scan(dest ...interface{}) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, d := range dest {
|
for i, d := range dest {
|
||||||
vr, _ := rows.nextColumn()
|
buf, fd, _ := rows.nextColumn()
|
||||||
|
|
||||||
if d == nil {
|
if d == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if s, ok := d.(pgtype.BinaryDecoder); ok && vr.Type().FormatCode == BinaryFormatCode {
|
if s, ok := d.(pgtype.BinaryDecoder); ok && fd.FormatCode == BinaryFormatCode {
|
||||||
err = s.DecodeBinary(rows.conn.ConnInfo, vr.bytes())
|
err = s.DecodeBinary(rows.conn.ConnInfo, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rows.Fatal(scanArgError{col: i, err: err})
|
rows.Fatal(scanArgError{col: i, err: err})
|
||||||
}
|
}
|
||||||
} else if s, ok := d.(pgtype.TextDecoder); ok && vr.Type().FormatCode == TextFormatCode {
|
} else if s, ok := d.(pgtype.TextDecoder); ok && fd.FormatCode == TextFormatCode {
|
||||||
err = s.DecodeText(rows.conn.ConnInfo, vr.bytes())
|
err = s.DecodeText(rows.conn.ConnInfo, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rows.Fatal(scanArgError{col: i, err: err})
|
rows.Fatal(scanArgError{col: i, err: err})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if dt, ok := rows.conn.ConnInfo.DataTypeForOid(vr.Type().DataType); ok {
|
if dt, ok := rows.conn.ConnInfo.DataTypeForOid(fd.DataType); ok {
|
||||||
value := dt.Value
|
value := dt.Value
|
||||||
switch vr.Type().FormatCode {
|
switch fd.FormatCode {
|
||||||
case TextFormatCode:
|
case TextFormatCode:
|
||||||
if textDecoder, ok := value.(pgtype.TextDecoder); ok {
|
if textDecoder, ok := value.(pgtype.TextDecoder); ok {
|
||||||
err = textDecoder.DecodeText(rows.conn.ConnInfo, vr.bytes())
|
err = textDecoder.DecodeText(rows.conn.ConnInfo, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vr.Fatal(err)
|
rows.Fatal(scanArgError{col: i, err: err})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vr.Fatal(fmt.Errorf("%T is not a pgtype.TextDecoder", value))
|
rows.Fatal(scanArgError{col: i, err: fmt.Errorf("%T is not a pgtype.TextDecoder", value)})
|
||||||
}
|
}
|
||||||
case BinaryFormatCode:
|
case BinaryFormatCode:
|
||||||
if binaryDecoder, ok := value.(pgtype.BinaryDecoder); ok {
|
if binaryDecoder, ok := value.(pgtype.BinaryDecoder); ok {
|
||||||
err = binaryDecoder.DecodeBinary(rows.conn.ConnInfo, vr.bytes())
|
err = binaryDecoder.DecodeBinary(rows.conn.ConnInfo, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vr.Fatal(err)
|
rows.Fatal(scanArgError{col: i, err: err})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vr.Fatal(fmt.Errorf("%T is not a pgtype.BinaryDecoder", value))
|
rows.Fatal(scanArgError{col: i, err: fmt.Errorf("%T is not a pgtype.BinaryDecoder", value)})
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
vr.Fatal(fmt.Errorf("unknown format code: %v", vr.Type().FormatCode))
|
rows.Fatal(scanArgError{col: i, err: fmt.Errorf("unknown format code: %v", fd.FormatCode)})
|
||||||
}
|
}
|
||||||
|
|
||||||
if vr.Err() == nil {
|
if rows.Err() == nil {
|
||||||
if scanner, ok := d.(sql.Scanner); ok {
|
if scanner, ok := d.(sql.Scanner); ok {
|
||||||
sqlSrc, err := pgtype.DatabaseSQLValue(rows.conn.ConnInfo, value)
|
sqlSrc, err := pgtype.DatabaseSQLValue(rows.conn.ConnInfo, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -257,16 +254,13 @@ func (rows *Rows) Scan(dest ...interface{}) (err error) {
|
|||||||
rows.Fatal(scanArgError{col: i, err: err})
|
rows.Fatal(scanArgError{col: i, err: err})
|
||||||
}
|
}
|
||||||
} else if err := value.AssignTo(d); err != nil {
|
} else if err := value.AssignTo(d); err != nil {
|
||||||
vr.Fatal(err)
|
rows.Fatal(scanArgError{col: i, err: err})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rows.Fatal(scanArgError{col: i, err: fmt.Errorf("unknown oid: %v", vr.Type().DataType)})
|
rows.Fatal(scanArgError{col: i, err: fmt.Errorf("unknown oid: %v", fd.DataType)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if vr.Err() != nil {
|
|
||||||
rows.Fatal(scanArgError{col: i, err: vr.Err()})
|
|
||||||
}
|
|
||||||
|
|
||||||
if rows.Err() != nil {
|
if rows.Err() != nil {
|
||||||
return rows.Err()
|
return rows.Err()
|
||||||
@@ -285,23 +279,23 @@ func (rows *Rows) Values() ([]interface{}, error) {
|
|||||||
values := make([]interface{}, 0, len(rows.fields))
|
values := make([]interface{}, 0, len(rows.fields))
|
||||||
|
|
||||||
for range rows.fields {
|
for range rows.fields {
|
||||||
vr, _ := rows.nextColumn()
|
buf, fd, _ := rows.nextColumn()
|
||||||
|
|
||||||
if vr.Len() == -1 {
|
if buf == nil {
|
||||||
values = append(values, nil)
|
values = append(values, nil)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if dt, ok := rows.conn.ConnInfo.DataTypeForOid(vr.Type().DataType); ok {
|
if dt, ok := rows.conn.ConnInfo.DataTypeForOid(fd.DataType); ok {
|
||||||
value := dt.Value
|
value := dt.Value
|
||||||
|
|
||||||
switch vr.Type().FormatCode {
|
switch fd.FormatCode {
|
||||||
case TextFormatCode:
|
case TextFormatCode:
|
||||||
decoder := value.(pgtype.TextDecoder)
|
decoder := value.(pgtype.TextDecoder)
|
||||||
if decoder == nil {
|
if decoder == nil {
|
||||||
decoder = &pgtype.GenericText{}
|
decoder = &pgtype.GenericText{}
|
||||||
}
|
}
|
||||||
err := decoder.DecodeText(rows.conn.ConnInfo, vr.bytes())
|
err := decoder.DecodeText(rows.conn.ConnInfo, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rows.Fatal(err)
|
rows.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -311,7 +305,7 @@ func (rows *Rows) Values() ([]interface{}, error) {
|
|||||||
if decoder == nil {
|
if decoder == nil {
|
||||||
decoder = &pgtype.GenericBinary{}
|
decoder = &pgtype.GenericBinary{}
|
||||||
}
|
}
|
||||||
err := decoder.DecodeBinary(rows.conn.ConnInfo, vr.bytes())
|
err := decoder.DecodeBinary(rows.conn.ConnInfo, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rows.Fatal(err)
|
rows.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -323,10 +317,6 @@ func (rows *Rows) Values() ([]interface{}, error) {
|
|||||||
rows.Fatal(errors.New("Unknown type"))
|
rows.Fatal(errors.New("Unknown type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if vr.Err() != nil {
|
|
||||||
rows.Fatal(vr.Err())
|
|
||||||
}
|
|
||||||
|
|
||||||
if rows.Err() != nil {
|
if rows.Err() != nil {
|
||||||
return nil, rows.Err()
|
return nil, rows.Err()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ No longer can read raw bytes of any value into a []byte. Use pgtype.GenericBinar
|
|||||||
|
|
||||||
OID constants moved from pgx to pgtype package
|
OID constants moved from pgx to pgtype package
|
||||||
|
|
||||||
|
Removed ValueReader
|
||||||
|
|
||||||
|
Replaced Scanner, Encoder, and PgxScanner interfaces with pgtype system
|
||||||
|
|
||||||
## TODO / Possible / Investigate
|
## TODO / Possible / Investigate
|
||||||
|
|
||||||
Organize errors better
|
Organize errors better
|
||||||
@@ -46,7 +50,7 @@ Remove names from prepared statements - use database/sql style objects
|
|||||||
|
|
||||||
Better way of handling text/binary protocol choice than pgx.DefaultTypeFormats or manually editing a PreparedStatement. Possibly an optional part of preparing a statement is specifying the format and/or a decoder. Or maybe it is part of a QueryEx call... Could be very interesting to make encoding and decoding possible without being a method of the type. This could drastically clean up those huge type switches.
|
Better way of handling text/binary protocol choice than pgx.DefaultTypeFormats or manually editing a PreparedStatement. Possibly an optional part of preparing a statement is specifying the format and/or a decoder. Or maybe it is part of a QueryEx call... Could be very interesting to make encoding and decoding possible without being a method of the type. This could drastically clean up those huge type switches.
|
||||||
|
|
||||||
dValueReader / msgReader cleanup
|
msgReader cleanup
|
||||||
|
|
||||||
Make easier / possible to mock Conn or ConnPool (https://github.com/jackc/pgx/pull/162)
|
Make easier / possible to mock Conn or ConnPool (https://github.com/jackc/pgx/pull/162)
|
||||||
|
|
||||||
|
|||||||
-166
@@ -1,166 +0,0 @@
|
|||||||
package pgx
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/jackc/pgx/pgtype"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ValueReader is used by the Scanner interface to decode values.
|
|
||||||
type ValueReader struct {
|
|
||||||
mr *msgReader
|
|
||||||
fd *FieldDescription
|
|
||||||
valueBytesRemaining int32
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Err returns any error that the ValueReader has experienced
|
|
||||||
func (r *ValueReader) Err() error {
|
|
||||||
return r.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fatal tells r that a Fatal error has occurred
|
|
||||||
func (r *ValueReader) Fatal(err error) {
|
|
||||||
r.err = err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the number of unread bytes
|
|
||||||
func (r *ValueReader) Len() int32 {
|
|
||||||
return r.valueBytesRemaining
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type returns the *FieldDescription of the value
|
|
||||||
func (r *ValueReader) Type() *FieldDescription {
|
|
||||||
return r.fd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ValueReader) ReadByte() byte {
|
|
||||||
if r.err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
r.valueBytesRemaining--
|
|
||||||
if r.valueBytesRemaining < 0 {
|
|
||||||
r.Fatal(errors.New("read past end of value"))
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.mr.readByte()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ValueReader) ReadInt16() int16 {
|
|
||||||
if r.err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
r.valueBytesRemaining -= 2
|
|
||||||
if r.valueBytesRemaining < 0 {
|
|
||||||
r.Fatal(errors.New("read past end of value"))
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.mr.readInt16()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ValueReader) ReadUint16() uint16 {
|
|
||||||
if r.err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
r.valueBytesRemaining -= 2
|
|
||||||
if r.valueBytesRemaining < 0 {
|
|
||||||
r.Fatal(errors.New("read past end of value"))
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.mr.readUint16()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ValueReader) ReadInt32() int32 {
|
|
||||||
if r.err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
r.valueBytesRemaining -= 4
|
|
||||||
if r.valueBytesRemaining < 0 {
|
|
||||||
r.Fatal(errors.New("read past end of value"))
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.mr.readInt32()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ValueReader) ReadUint32() uint32 {
|
|
||||||
if r.err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
r.valueBytesRemaining -= 4
|
|
||||||
if r.valueBytesRemaining < 0 {
|
|
||||||
r.Fatal(errors.New("read past end of value"))
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.mr.readUint32()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ValueReader) ReadInt64() int64 {
|
|
||||||
if r.err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
r.valueBytesRemaining -= 8
|
|
||||||
if r.valueBytesRemaining < 0 {
|
|
||||||
r.Fatal(errors.New("read past end of value"))
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.mr.readInt64()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ValueReader) ReadOid() pgtype.Oid {
|
|
||||||
return pgtype.Oid(r.ReadUint32())
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadString reads count bytes and returns as string
|
|
||||||
func (r *ValueReader) ReadString(count int32) string {
|
|
||||||
if r.err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
r.valueBytesRemaining -= count
|
|
||||||
if r.valueBytesRemaining < 0 {
|
|
||||||
r.Fatal(errors.New("read past end of value"))
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.mr.readString(count)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadBytes reads count bytes and returns as []byte
|
|
||||||
func (r *ValueReader) ReadBytes(count int32) []byte {
|
|
||||||
if r.err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if count < 0 {
|
|
||||||
r.Fatal(errors.New("count must not be negative"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
r.valueBytesRemaining -= count
|
|
||||||
if r.valueBytesRemaining < 0 {
|
|
||||||
r.Fatal(errors.New("read past end of value"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.mr.readBytes(count)
|
|
||||||
}
|
|
||||||
|
|
||||||
// bytes is a compatibility function for pgtype.TextDecoder and pgtype.BinaryDecoder
|
|
||||||
func (r *ValueReader) bytes() []byte {
|
|
||||||
if r.Len() >= 0 {
|
|
||||||
return r.ReadBytes(r.Len())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user