Add ConnConfig.PreferSimpleProtocol

Allows configuring on a connection basis to prefer the simple protocol /
disable implicit prepared statements.

refs #331
prefer-simple-protocol
Jack Christensen 2017-12-16 12:46:27 -06:00
parent 50627257f9
commit bd76a96882
3 changed files with 38 additions and 2 deletions

13
conn.go
View File

@ -75,6 +75,17 @@ type ConnConfig struct {
RuntimeParams map[string]string // Run-time parameters to set on connection as session default values (e.g. search_path or application_name)
OnNotice NoticeHandler // Callback function called when a notice response is received.
CustomConnInfo func(*Conn) (*pgtype.ConnInfo, error) // Callback function to implement connection strategies for different backends. crate, pgbouncer, pgpool, etc.
// PreferSimpleProtocol disables implicit prepared statement usage. By default
// pgx automatically uses the unnamed prepared statement for Query and
// QueryRow. It also uses a prepared statement when Exec has arguments. This
// can improve performance due to being able to use the binary format. It also
// does not rely on client side parameter sanitization. However, it does incur
// two round-trips per query and may be incompatible proxies such as
// PGBouncer. Setting PreferSimpleProtocol causes the simple protocol to be
// used by default. The same functionality can be controlled on a per query
// basis by setting QueryExOptions.SimpleProtocol.
PreferSimpleProtocol bool
}
func (cc *ConnConfig) networkAddress() (network, address string) {
@ -1586,7 +1597,7 @@ func (c *Conn) execEx(ctx context.Context, sql string, options *QueryExOptions,
err = c.termContext(err)
}()
if options != nil && options.SimpleProtocol {
if (options == nil && c.config.PreferSimpleProtocol) || (options != nil && options.SimpleProtocol) {
err = c.sanitizeAndSendSimpleQuery(sql, arguments...)
if err != nil {
return "", err

View File

@ -255,6 +255,31 @@ func TestConnectWithConnectionRefused(t *testing.T) {
}
}
func TestConnectWithPreferSimpleProtocol(t *testing.T) {
t.Parallel()
connConfig := *defaultConnConfig
connConfig.PreferSimpleProtocol = true
conn := mustConnect(t, connConfig)
defer closeConn(t, conn)
// If simple protocol is used we should be able to correctly scan the result
// into a pgtype.Text as the integer will have been encoded in text.
var s pgtype.Text
err := conn.QueryRow("select $1::int4", 42).Scan(&s)
if err != nil {
t.Fatal(err)
}
if s.Get() != "42" {
t.Fatalf(`expected "42", got %v`, s)
}
ensureConnValid(t, conn)
}
func TestConnectCustomDialer(t *testing.T) {
t.Parallel()

View File

@ -393,7 +393,7 @@ func (c *Conn) QueryEx(ctx context.Context, sql string, options *QueryExOptions,
return rows, rows.err
}
if options != nil && options.SimpleProtocol {
if (options == nil && c.config.PreferSimpleProtocol) || (options != nil && options.SimpleProtocol) {
err = c.sanitizeAndSendSimpleQuery(sql, args...)
if err != nil {
rows.fatal(err)