2
0

Create ROW helper for adhoc decoding of records

This commit is contained in:
Maxim Ivanov
2020-04-12 18:40:52 +01:00
parent 71ed747f3a
commit 368295d3ee
3 changed files with 50 additions and 0 deletions
+13
View File
@@ -71,7 +71,20 @@ create type mytype as (
}
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:
// First row: a=1 b=foo
// Second row: <nil>
// Adhoc: isNull=false a=2 b=bar
}
+28
View File
@@ -471,6 +471,34 @@ func ScanRowValue(ci *ConnInfo, src []byte, dst ...Value) error {
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() {
kindTypes = map[reflect.Kind]reflect.Type{
reflect.Bool: reflect.TypeOf(false),
+9
View File
@@ -158,6 +158,15 @@ type TextEncoder interface {
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 errBadStatus = errors.New("invalid status")