Skip to content

Commit d3dbf83

Browse files
committed
Allow pgxpool to more easily use LoadTypes
While LoadTypes is powerful on its own, retriving all salient type information in a single query, it is particularly powerful and useful when users of pgxpool can use this. To streamline its use, provide a helper function in pgxpool suitable for plugging directly into the AfterConnect configuration settings. It will load the types and register them, also reusing them if appropriate.
1 parent 7f85b19 commit d3dbf83

File tree

1 file changed

+65
-5
lines changed

1 file changed

+65
-5
lines changed

pgxpool/pool.go

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"math/rand"
7+
"os"
78
"runtime"
89
"strconv"
910
"sync"
@@ -12,14 +13,17 @@ import (
1213

1314
"github.com/jackc/pgx/v5"
1415
"github.com/jackc/pgx/v5/pgconn"
16+
"github.com/jackc/pgx/v5/pgtype"
1517
"github.com/jackc/puddle/v2"
1618
)
1719

18-
var defaultMaxConns = int32(4)
19-
var defaultMinConns = int32(0)
20-
var defaultMaxConnLifetime = time.Hour
21-
var defaultMaxConnIdleTime = time.Minute * 30
22-
var defaultHealthCheckPeriod = time.Minute
20+
var (
21+
defaultMaxConns = int32(4)
22+
defaultMinConns = int32(0)
23+
defaultMaxConnLifetime = time.Hour
24+
defaultMaxConnIdleTime = time.Minute * 30
25+
defaultHealthCheckPeriod = time.Minute
26+
)
2327

2428
type connResource struct {
2529
conn *pgx.Conn
@@ -102,6 +106,62 @@ type Pool struct {
102106
closeChan chan struct{}
103107
}
104108

109+
// AutoloadAfterConnect is suitable for assigning to the AfterConnect configuration setting.
110+
// It will automatically load the named types for each connection in an efficient manner,
111+
// performing a single query to the database backend. The underlying call to pgx.LoadTypes
112+
// is smart enough to also retrieve any related types required to support the definition of the
113+
// named types.
114+
// If reuseTypeMap is enabled, it is assumed that the OID mapping is stable across all database
115+
// backends in this pool, resulting in only needing to query when creating the initial connection;
116+
// subsequent connections will reuse the same OID type mapping.
117+
// Because it is not always possible for a client to know the database topology in the final usage
118+
// context, PGXPOOL_REUSE_TYPEMAP, when given a value of y or n, will take precedence over this argument.
119+
func AutoloadAfterConnect(typeNames []string, reuseTypeMap bool) func(context.Context, *pgx.Conn) error {
120+
if envValue := os.Getenv("PGXPOOL_REUSE_TYPEMAP"); envValue != "" {
121+
switch envValue {
122+
case "y":
123+
reuseTypeMap = true
124+
case "n":
125+
reuseTypeMap = false
126+
}
127+
}
128+
if reuseTypeMap {
129+
mutex := new(sync.Mutex)
130+
var types []*pgtype.Type
131+
return func(ctx context.Context, conn *pgx.Conn) error {
132+
if types != nil {
133+
// avoid acquiring the mutex if the types are already available
134+
conn.TypeMap().RegisterTypes(types)
135+
return nil
136+
}
137+
mutex.Lock()
138+
defer mutex.Unlock()
139+
var err error
140+
141+
// types may have become available while waiting for the mutex
142+
if types != nil {
143+
conn.TypeMap().RegisterTypes(types)
144+
return nil
145+
}
146+
types, err = conn.LoadTypes(ctx, typeNames)
147+
if err != nil {
148+
types = nil
149+
return err
150+
}
151+
conn.TypeMap().RegisterTypes(types)
152+
return nil
153+
}
154+
}
155+
return func(ctx context.Context, conn *pgx.Conn) error {
156+
types, err := conn.LoadTypes(ctx, typeNames)
157+
if err != nil {
158+
return err
159+
}
160+
conn.TypeMap().RegisterTypes(types)
161+
return nil
162+
}
163+
}
164+
105165
// Config is the configuration struct for creating a pool. It must be created by [ParseConfig] and then it can be
106166
// modified.
107167
type Config struct {

0 commit comments

Comments
 (0)