1package pgtype_test
2
3import (
4	"testing"
5
6	"github.com/jackc/pgio"
7	"github.com/jackc/pgtype"
8	"github.com/stretchr/testify/require"
9)
10
11type MyCompositeRaw struct {
12	A int32
13	B *string
14}
15
16func (src MyCompositeRaw) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) {
17	buf = pgio.AppendUint32(buf, 2)
18
19	buf = pgio.AppendUint32(buf, pgtype.Int4OID)
20	buf = pgio.AppendInt32(buf, 4)
21	buf = pgio.AppendInt32(buf, src.A)
22
23	buf = pgio.AppendUint32(buf, pgtype.TextOID)
24	if src.B != nil {
25		buf = pgio.AppendInt32(buf, int32(len(*src.B)))
26		buf = append(buf, (*src.B)...)
27	} else {
28		buf = pgio.AppendInt32(buf, -1)
29	}
30
31	return buf, nil
32}
33
34func (dst *MyCompositeRaw) DecodeBinary(ci *pgtype.ConnInfo, src []byte) error {
35	a := pgtype.Int4{}
36	b := pgtype.Text{}
37
38	scanner := pgtype.NewCompositeBinaryScanner(ci, src)
39	scanner.ScanDecoder(&a)
40	scanner.ScanDecoder(&b)
41
42	if scanner.Err() != nil {
43		return scanner.Err()
44	}
45
46	dst.A = a.Int
47	if b.Status == pgtype.Present {
48		dst.B = &b.String
49	} else {
50		dst.B = nil
51	}
52
53	return nil
54}
55
56var x []byte
57
58func BenchmarkBinaryEncodingManual(b *testing.B) {
59	buf := make([]byte, 0, 128)
60	ci := pgtype.NewConnInfo()
61	v := MyCompositeRaw{4, ptrS("ABCDEFG")}
62
63	b.ResetTimer()
64	for n := 0; n < b.N; n++ {
65		buf, _ = v.EncodeBinary(ci, buf[:0])
66	}
67	x = buf
68}
69
70func BenchmarkBinaryEncodingHelper(b *testing.B) {
71	buf := make([]byte, 0, 128)
72	ci := pgtype.NewConnInfo()
73	v := MyType{4, ptrS("ABCDEFG")}
74
75	b.ResetTimer()
76	for n := 0; n < b.N; n++ {
77		buf, _ = v.EncodeBinary(ci, buf[:0])
78	}
79	x = buf
80}
81
82func BenchmarkBinaryEncodingComposite(b *testing.B) {
83	buf := make([]byte, 0, 128)
84	ci := pgtype.NewConnInfo()
85	f1 := 2
86	f2 := ptrS("bar")
87	c, err := pgtype.NewCompositeType("test", []pgtype.CompositeTypeField{
88		{"a", pgtype.Int4OID},
89		{"b", pgtype.TextOID},
90	}, ci)
91	require.NoError(b, err)
92
93	b.ResetTimer()
94	for n := 0; n < b.N; n++ {
95		c.Set([]interface{}{f1, f2})
96		buf, _ = c.EncodeBinary(ci, buf[:0])
97	}
98	x = buf
99}
100
101func BenchmarkBinaryEncodingJSON(b *testing.B) {
102	buf := make([]byte, 0, 128)
103	ci := pgtype.NewConnInfo()
104	v := MyCompositeRaw{4, ptrS("ABCDEFG")}
105	j := pgtype.JSON{}
106
107	b.ResetTimer()
108	for n := 0; n < b.N; n++ {
109		j.Set(v)
110		buf, _ = j.EncodeBinary(ci, buf[:0])
111	}
112	x = buf
113}
114
115var dstRaw MyCompositeRaw
116
117func BenchmarkBinaryDecodingManual(b *testing.B) {
118	ci := pgtype.NewConnInfo()
119	buf, _ := MyType{4, ptrS("ABCDEFG")}.EncodeBinary(ci, nil)
120	dst := MyCompositeRaw{}
121
122	b.ResetTimer()
123	for n := 0; n < b.N; n++ {
124		err := dst.DecodeBinary(ci, buf)
125		E(err)
126	}
127	dstRaw = dst
128}
129
130var dstMyType MyType
131
132func BenchmarkBinaryDecodingHelpers(b *testing.B) {
133	ci := pgtype.NewConnInfo()
134	buf, _ := MyType{4, ptrS("ABCDEFG")}.EncodeBinary(ci, nil)
135	dst := MyType{}
136
137	b.ResetTimer()
138	for n := 0; n < b.N; n++ {
139		err := dst.DecodeBinary(ci, buf)
140		E(err)
141	}
142	dstMyType = dst
143}
144
145var gf1 int
146var gf2 *string
147
148func BenchmarkBinaryDecodingCompositeScan(b *testing.B) {
149	ci := pgtype.NewConnInfo()
150	buf, _ := MyType{4, ptrS("ABCDEFG")}.EncodeBinary(ci, nil)
151	var f1 int
152	var f2 *string
153
154	c, err := pgtype.NewCompositeType("test", []pgtype.CompositeTypeField{
155		{"a", pgtype.Int4OID},
156		{"b", pgtype.TextOID},
157	}, ci)
158	require.NoError(b, err)
159
160	b.ResetTimer()
161	for n := 0; n < b.N; n++ {
162		err := c.DecodeBinary(ci, buf)
163		if err != nil {
164			b.Fatal(err)
165		}
166		err = c.AssignTo([]interface{}{&f1, &f2})
167		if err != nil {
168			b.Fatal(err)
169		}
170	}
171	gf1 = f1
172	gf2 = f2
173}
174
175func BenchmarkBinaryDecodingJSON(b *testing.B) {
176	ci := pgtype.NewConnInfo()
177	j := pgtype.JSON{}
178	j.Set(MyCompositeRaw{4, ptrS("ABCDEFG")})
179	buf, _ := j.EncodeBinary(ci, nil)
180
181	j = pgtype.JSON{}
182	dst := MyCompositeRaw{}
183
184	b.ResetTimer()
185	for n := 0; n < b.N; n++ {
186		err := j.DecodeBinary(ci, buf)
187		E(err)
188		err = j.AssignTo(&dst)
189		E(err)
190	}
191	dstRaw = dst
192}
193