Create ROW helper for adhoc decoding of records
This commit is contained in:
@@ -71,7 +71,20 @@ create type mytype as (
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Second row: %v\n", result)
|
fmt.Printf("Second row: %v\n", result)
|
||||||
|
|
||||||
|
// Adhoc rows can be decoded inplace without boilerplate (works with composite types too)
|
||||||
|
var isNull bool
|
||||||
|
var a int
|
||||||
|
var b *string
|
||||||
|
|
||||||
|
if err = conn.QueryRow(context.Background(), "select (2, 'bar')::mytype", pgx.QueryResultFormats{pgx.BinaryFormatCode}).Scan(pgtype.ROW(&isNull, &a, &b)); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Adhoc: isNull=%v a=%d b=%s", isNull, a, *b)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// First row: a=1 b=foo
|
// First row: a=1 b=foo
|
||||||
// Second row: <nil>
|
// Second row: <nil>
|
||||||
|
// Adhoc: isNull=false a=2 b=bar
|
||||||
}
|
}
|
||||||
|
|||||||
+28
@@ -471,6 +471,34 @@ func ScanRowValue(ci *ConnInfo, src []byte, dst ...Value) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ROW allows deconstructing row values (records and composite types) into
|
||||||
|
// fields directly without creating your own type and implementing decoder interfaces
|
||||||
|
func ROW(isNull *bool, fields ...interface{}) BinaryDecoderFunc {
|
||||||
|
return func(ci *ConnInfo, src []byte) error {
|
||||||
|
var record Record
|
||||||
|
if err := record.DecodeBinary(ci, src); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.Status == Null {
|
||||||
|
*isNull = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(record.Fields) != len(fields) {
|
||||||
|
return errors.Errorf("can't scan row value, number of fields don't match: row fields count=%d desired fields count=%d", len(record.Fields), len(fields))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, f := range record.Fields {
|
||||||
|
if err := f.AssignTo(fields[i]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
kindTypes = map[reflect.Kind]reflect.Type{
|
kindTypes = map[reflect.Kind]reflect.Type{
|
||||||
reflect.Bool: reflect.TypeOf(false),
|
reflect.Bool: reflect.TypeOf(false),
|
||||||
|
|||||||
@@ -158,6 +158,15 @@ type TextEncoder interface {
|
|||||||
EncodeText(ci *ConnInfo, buf []byte) (newBuf []byte, err error)
|
EncodeText(ci *ConnInfo, buf []byte) (newBuf []byte, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//The BinaryDecoderFunc type is an adapter to allow the use of ordinary functions as BinaryDecoder types.
|
||||||
|
// If f is a function with the appropriate signature, BinaryDecoderFunc(f) is a BinaryDecoder that calls f.
|
||||||
|
type BinaryDecoderFunc func(ci *ConnInfo, src []byte) error
|
||||||
|
|
||||||
|
// DecodeBinary calls f(ci, src)
|
||||||
|
func (f BinaryDecoderFunc) DecodeBinary(ci *ConnInfo, src []byte) error {
|
||||||
|
return f(ci, src)
|
||||||
|
}
|
||||||
|
|
||||||
var errUndefined = errors.New("cannot encode status undefined")
|
var errUndefined = errors.New("cannot encode status undefined")
|
||||||
var errBadStatus = errors.New("invalid status")
|
var errBadStatus = errors.New("invalid status")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user