From e283f322e1082cff623f19ac046fe1b5ee2b81ed Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Mon, 20 Apr 2020 22:38:20 +0000 Subject: [PATCH] Composite().Row() helper for working with composites without registration --- composite.go | 18 ++++++++++++++++++ composite_bench_test.go | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/composite.go b/composite.go index 1caa24d6..d9f47d92 100644 --- a/composite.go +++ b/composite.go @@ -92,6 +92,24 @@ func (src composite) DecodeBinary(ci *ConnInfo, buf []byte) (err error) { return errors.New("Pass pgtype.Row() to Scan to deconstruct Composite") } +// Row method creates composite BinaryEncoder. It's main purpose +// is to build composite query argument inplace without registering +// pgtype.Composite in ConnInfo first +func (src composite) Row(values ...interface{}) BinaryEncoderFunc { + return func(ci *ConnInfo, buf []byte) ([]byte, error) { + if len(values) != len(src.fields) { + return nil, errors.Errorf("Number of fields don't match. Composite has %d fields", len(src.fields)) + } + for i, v := range values { + if err := src.fields[i].Set(v); err != nil { + return nil, err + } + } + src.status = Present + return src.EncodeBinary(ci, buf) + } +} + // DecodeBinary is called when pgtype.Row() is passed to Scan() to // deconstruct composite value func (r rowValue) DecodeBinary(ci *ConnInfo, src []byte) error { diff --git a/composite_bench_test.go b/composite_bench_test.go index 30e48ae7..67dcf1fd 100644 --- a/composite_bench_test.go +++ b/composite_bench_test.go @@ -110,6 +110,18 @@ func BenchmarkBinaryEncodingRow(b *testing.B) { } x = buf } +func BenchmarkBinaryEncodingRowInplace(b *testing.B) { + buf := make([]byte, 0, 128) + ci := pgtype.NewConnInfo() + f1 := 2 + f2 := ptrS("bar") + + b.ResetTimer() + for n := 0; n < b.N; n++ { + buf, _ = pgtype.Composite(&pgtype.Int4{}, &pgtype.Text{}).Row(f1, f2).EncodeBinary(ci, buf[:0]) + } + x = buf +} var dstRaw MyCompositeRaw