1package pgx_test
2
3import (
4	"context"
5	"os"
6	"testing"
7
8	"github.com/jackc/pgconn"
9	"github.com/jackc/pgconn/stmtcache"
10	"github.com/jackc/pgx/v4"
11	"github.com/stretchr/testify/assert"
12	"github.com/stretchr/testify/require"
13)
14
15func TestPgbouncerStatementCacheDescribe(t *testing.T) {
16	connString := os.Getenv("PGX_TEST_PGBOUNCER_CONN_STRING")
17	if connString == "" {
18		t.Skipf("Skipping due to missing environment variable %v", "PGX_TEST_PGBOUNCER_CONN_STRING")
19	}
20
21	config := mustParseConfig(t, connString)
22	config.BuildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
23		return stmtcache.New(conn, stmtcache.ModeDescribe, 1024)
24	}
25
26	testPgbouncer(t, config, 10, 100)
27}
28
29func TestPgbouncerSimpleProtocol(t *testing.T) {
30	connString := os.Getenv("PGX_TEST_PGBOUNCER_CONN_STRING")
31	if connString == "" {
32		t.Skipf("Skipping due to missing environment variable %v", "PGX_TEST_PGBOUNCER_CONN_STRING")
33	}
34
35	config := mustParseConfig(t, connString)
36	config.BuildStatementCache = nil
37	config.PreferSimpleProtocol = true
38
39	testPgbouncer(t, config, 10, 100)
40}
41
42func testPgbouncer(t *testing.T, config *pgx.ConnConfig, workers, iterations int) {
43	doneChan := make(chan struct{})
44
45	for i := 0; i < workers; i++ {
46		go func() {
47			defer func() { doneChan <- struct{}{} }()
48			conn, err := pgx.ConnectConfig(context.Background(), config)
49			require.Nil(t, err)
50			defer closeConn(t, conn)
51
52			for i := 0; i < iterations; i++ {
53				var i32 int32
54				var i64 int64
55				var f32 float32
56				var s string
57				var s2 string
58				err = conn.QueryRow(context.Background(), "select 1::int4, 2::int8, 3::float4, 'hi'::text").Scan(&i32, &i64, &f32, &s)
59				require.NoError(t, err)
60				assert.Equal(t, int32(1), i32)
61				assert.Equal(t, int64(2), i64)
62				assert.Equal(t, float32(3), f32)
63				assert.Equal(t, "hi", s)
64
65				err = conn.QueryRow(context.Background(), "select 1::int8, 2::float4, 'bye'::text, 4::int4, 'whatever'::text").Scan(&i64, &f32, &s, &i32, &s2)
66				require.NoError(t, err)
67				assert.Equal(t, int64(1), i64)
68				assert.Equal(t, float32(2), f32)
69				assert.Equal(t, "bye", s)
70				assert.Equal(t, int32(4), i32)
71				assert.Equal(t, "whatever", s2)
72			}
73		}()
74	}
75
76	for i := 0; i < workers; i++ {
77		<-doneChan
78	}
79
80}
81