2
0

Merge SetFields functionality into Set

This commit is contained in:
Jack Christensen
2020-05-12 08:35:45 -05:00
parent c41160bcbb
commit 247043b597
3 changed files with 61 additions and 22 deletions
+1 -1
View File
@@ -104,7 +104,7 @@ func BenchmarkBinaryEncodingComposite(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
c.SetFields(f1, f2)
c.Set([]interface{}{f1, f2})
buf, _ = c.EncodeBinary(ci, buf[:0])
}
x = buf
+15 -20
View File
@@ -20,13 +20,17 @@ type CompositeType struct {
// To read composite fields back pass result of Scan() method
// to query Scan function.
func NewCompositeType(fields ...Value) *CompositeType {
return &CompositeType{fields, Present}
return &CompositeType{fields, Undefined}
}
func (src CompositeType) Get() interface{} {
switch src.status {
case Present:
return src
results := make([]interface{}, len(src.fields))
for i := range results {
results[i] = src.fields[i].Get()
}
return results
case Null:
return nil
default:
@@ -34,17 +38,16 @@ func (src CompositeType) Get() interface{} {
}
}
// Set is called internally when passing query arguments.
func (dst *CompositeType) Set(src interface{}) error {
if src == nil {
*dst = CompositeType{status: Null}
dst.status = Null
return nil
}
switch value := src.(type) {
case []Value:
case []interface{}:
if len(value) != len(dst.fields) {
return errors.Errorf("Number of fields don't match. Composite has %d fields", len(dst.fields))
return errors.Errorf("Number of fields don't match. CompositeType has %d fields", len(dst.fields))
}
for i, v := range value {
if err := dst.fields[i].Set(v); err != nil {
@@ -52,6 +55,12 @@ func (dst *CompositeType) Set(src interface{}) error {
}
}
dst.status = Present
case *[]interface{}:
if value == nil {
dst.status = Null
return nil
}
return dst.Set(*value)
default:
return errors.Errorf("Can not convert %v to Composite", src)
}
@@ -138,20 +147,6 @@ func (src CompositeType) Scan(isNull *bool, dst ...interface{}) BinaryDecoderFun
}
}
// SetFields sets Composite's fields to corresponding values
func (dst *CompositeType) SetFields(values ...interface{}) error {
if len(values) != len(dst.fields) {
return errors.Errorf("Number of fields don't match. Composite has %d fields", len(dst.fields))
}
for i, v := range values {
if err := dst.fields[i].Set(v); err != nil {
return err
}
}
dst.status = Present
return nil
}
type CompositeBinaryScanner struct {
rp int
src []byte
+45 -1
View File
@@ -4,11 +4,55 @@ import (
"context"
"fmt"
"os"
"testing"
"github.com/jackc/pgtype"
pgx "github.com/jackc/pgx/v4"
"github.com/stretchr/testify/assert"
)
func TestCompositeTypeSetAndGet(t *testing.T) {
ct := pgtype.NewCompositeType(&pgtype.Text{}, &pgtype.Int4{})
assert.Equal(t, pgtype.Undefined, ct.Get())
nilTests := []struct {
src interface{}
}{
{nil}, // nil interface
{(*[]interface{})(nil)}, // typed nil
}
for i, tt := range nilTests {
err := ct.Set(tt.src)
assert.NoErrorf(t, err, "%d", i)
assert.Equal(t, nil, ct.Get())
}
compatibleValuesTests := []struct {
src []interface{}
expected []interface{}
}{
{
src: []interface{}{"foo", int32(42)},
expected: []interface{}{"foo", int32(42)},
},
{
src: []interface{}{nil, nil},
expected: []interface{}{nil, nil},
},
{
src: []interface{}{&pgtype.Text{String: "hi", Status: pgtype.Present}, &pgtype.Int4{Int: 7, Status: pgtype.Present}},
expected: []interface{}{"hi", int32(7)},
},
}
for i, tt := range compatibleValuesTests {
err := ct.Set(tt.src)
assert.NoErrorf(t, err, "%d", i)
assert.EqualValues(t, tt.expected, ct.Get())
}
}
//ExampleComposite demonstrates use of Row() function to pass and receive
// back composite types without creating boilderplate custom types.
func Example_composite() {
@@ -32,7 +76,7 @@ create type mytype as (
var b *string
c := pgtype.NewCompositeType(&pgtype.Int4{}, &pgtype.Text{})
c.SetFields(2, "bar")
c.Set([]interface{}{2, "bar"})
err = conn.QueryRow(context.Background(), "select $1::mytype", qrf, c).
Scan(c.Scan(&isNull, &a, &b))