Remove ConnConfig.BuildStatementCache

pull/1170/head
Jack Christensen 2022-03-12 09:23:40 -06:00
parent f27178ba85
commit 8e341e20f3
9 changed files with 124 additions and 219 deletions

View File

@ -7,7 +7,6 @@ import (
"testing"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/internal/stmtcache"
"github.com/jackc/pgx/v5/pgconn"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -249,7 +248,9 @@ func TestConnSendBatchWithPreparedStatementAndStatementCacheDisabled(t *testing.
config, err := pgx.ParseConfig(os.Getenv("PGX_TEST_DATABASE"))
require.NoError(t, err)
config.BuildStatementCache = nil
config.DefaultQueryExecMode = pgx.QueryExecModeDescribeExec
config.StatementCacheCapacity = 0
config.DescriptionCacheCapacity = 0
conn := mustConnect(t, config)
defer closeConn(t, conn)
@ -653,7 +654,9 @@ func TestConnBeginBatchDeferredError(t *testing.T) {
func TestConnSendBatchNoStatementCache(t *testing.T) {
config := mustParseConfig(t, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = nil
config.DefaultQueryExecMode = pgx.QueryExecModeDescribeExec
config.StatementCacheCapacity = 0
config.DescriptionCacheCapacity = 0
conn := mustConnect(t, config)
defer closeConn(t, conn)
@ -663,9 +666,8 @@ func TestConnSendBatchNoStatementCache(t *testing.T) {
func TestConnSendBatchPrepareStatementCache(t *testing.T) {
config := mustParseConfig(t, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModePrepare, 32)
}
config.DefaultQueryExecMode = pgx.QueryExecModeCacheStatement
config.StatementCacheCapacity = 32
conn := mustConnect(t, config)
defer closeConn(t, conn)
@ -675,9 +677,8 @@ func TestConnSendBatchPrepareStatementCache(t *testing.T) {
func TestConnSendBatchDescribeStatementCache(t *testing.T) {
config := mustParseConfig(t, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModeDescribe, 32)
}
config.DefaultQueryExecMode = pgx.QueryExecModeCacheDescribe
config.DescriptionCacheCapacity = 32
conn := mustConnect(t, config)
defer closeConn(t, conn)

View File

@ -13,7 +13,6 @@ import (
"time"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/internal/stmtcache"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgtype"
"github.com/stretchr/testify/require"
@ -21,7 +20,9 @@ import (
func BenchmarkMinimalUnpreparedSelectWithoutStatementCache(b *testing.B) {
config := mustParseConfig(b, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = nil
config.DefaultQueryExecMode = pgx.QueryExecModeDescribeExec
config.StatementCacheCapacity = 0
config.DescriptionCacheCapacity = 0
conn := mustConnect(b, config)
defer closeConn(b, conn)
@ -43,9 +44,9 @@ func BenchmarkMinimalUnpreparedSelectWithoutStatementCache(b *testing.B) {
func BenchmarkMinimalUnpreparedSelectWithStatementCacheModeDescribe(b *testing.B) {
config := mustParseConfig(b, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModeDescribe, 32)
}
config.DefaultQueryExecMode = pgx.QueryExecModeCacheDescribe
config.StatementCacheCapacity = 0
config.DescriptionCacheCapacity = 32
conn := mustConnect(b, config)
defer closeConn(b, conn)
@ -67,9 +68,9 @@ func BenchmarkMinimalUnpreparedSelectWithStatementCacheModeDescribe(b *testing.B
func BenchmarkMinimalUnpreparedSelectWithStatementCacheModePrepare(b *testing.B) {
config := mustParseConfig(b, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModePrepare, 32)
}
config.DefaultQueryExecMode = pgx.QueryExecModeCacheStatement
config.StatementCacheCapacity = 32
config.DescriptionCacheCapacity = 0
conn := mustConnect(b, config)
defer closeConn(b, conn)
@ -723,7 +724,9 @@ func BenchmarkWrite10000RowsViaCopy(b *testing.B) {
func BenchmarkMultipleQueriesNonBatchNoStatementCache(b *testing.B) {
config := mustParseConfig(b, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = nil
config.DefaultQueryExecMode = pgx.QueryExecModeDescribeExec
config.StatementCacheCapacity = 0
config.DescriptionCacheCapacity = 0
conn := mustConnect(b, config)
defer closeConn(b, conn)
@ -733,9 +736,9 @@ func BenchmarkMultipleQueriesNonBatchNoStatementCache(b *testing.B) {
func BenchmarkMultipleQueriesNonBatchPrepareStatementCache(b *testing.B) {
config := mustParseConfig(b, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModePrepare, 32)
}
config.DefaultQueryExecMode = pgx.QueryExecModeCacheStatement
config.StatementCacheCapacity = 32
config.DescriptionCacheCapacity = 0
conn := mustConnect(b, config)
defer closeConn(b, conn)
@ -745,9 +748,9 @@ func BenchmarkMultipleQueriesNonBatchPrepareStatementCache(b *testing.B) {
func BenchmarkMultipleQueriesNonBatchDescribeStatementCache(b *testing.B) {
config := mustParseConfig(b, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModeDescribe, 32)
}
config.DefaultQueryExecMode = pgx.QueryExecModeCacheDescribe
config.StatementCacheCapacity = 0
config.DescriptionCacheCapacity = 32
conn := mustConnect(b, config)
defer closeConn(b, conn)
@ -783,7 +786,9 @@ func benchmarkMultipleQueriesNonBatch(b *testing.B, conn *pgx.Conn, queryCount i
func BenchmarkMultipleQueriesBatchNoStatementCache(b *testing.B) {
config := mustParseConfig(b, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = nil
config.DefaultQueryExecMode = pgx.QueryExecModeDescribeExec
config.StatementCacheCapacity = 0
config.DescriptionCacheCapacity = 0
conn := mustConnect(b, config)
defer closeConn(b, conn)
@ -793,9 +798,9 @@ func BenchmarkMultipleQueriesBatchNoStatementCache(b *testing.B) {
func BenchmarkMultipleQueriesBatchPrepareStatementCache(b *testing.B) {
config := mustParseConfig(b, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModePrepare, 32)
}
config.DefaultQueryExecMode = pgx.QueryExecModeCacheStatement
config.StatementCacheCapacity = 32
config.DescriptionCacheCapacity = 0
conn := mustConnect(b, config)
defer closeConn(b, conn)
@ -805,9 +810,9 @@ func BenchmarkMultipleQueriesBatchPrepareStatementCache(b *testing.B) {
func BenchmarkMultipleQueriesBatchDescribeStatementCache(b *testing.B) {
config := mustParseConfig(b, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModeDescribe, 32)
}
config.DefaultQueryExecMode = pgx.QueryExecModeCacheDescribe
config.StatementCacheCapacity = 0
config.DescriptionCacheCapacity = 32
conn := mustConnect(b, config)
defer closeConn(b, conn)

94
conn.go
View File

@ -26,9 +26,13 @@ type ConnConfig struct {
// Original connection string that was parsed into config.
connString string
// BuildStatementCache creates the stmtcache.Cache implementation for connections created with this config. Set
// to nil to disable automatic prepared statements.
BuildStatementCache BuildStatementCacheFunc
// StatementCacheCapacity is maximum size of the statement cache used when executing a query with "cache_statement"
// query exec mode.
StatementCacheCapacity int
// DescriptionCacheCapacity is the maximum size of the description cache used when executing a query with
// "cache_describe" query exec mode.
DescriptionCacheCapacity int
// DefaultQueryExecMode controls the default mode for executing queries. By default pgx uses the extended protocol
// and automatically prepares and caches prepared statements. However, this may be incompatible with proxies such as
@ -52,16 +56,14 @@ func (cc *ConnConfig) Copy() *ConnConfig {
// ConnString returns the connection string as parsed by pgx.ParseConfig into pgx.ConnConfig.
func (cc *ConnConfig) ConnString() string { return cc.connString }
// BuildStatementCacheFunc is a function that can be used to create a stmtcache.Cache implementation for connection.
type BuildStatementCacheFunc func(conn *pgconn.PgConn) stmtcache.Cache
// Conn is a PostgreSQL connection handle. It is not safe for concurrent usage. Use a connection pool to manage access
// to multiple database connections from multiple goroutines.
type Conn struct {
pgConn *pgconn.PgConn
config *ConnConfig // config used when establishing this connection
preparedStatements map[string]*pgconn.StatementDescription
stmtcache stmtcache.Cache
statementCache stmtcache.Cache
descriptionCache stmtcache.Cache
logger Logger
logLevel LogLevel
@ -115,27 +117,24 @@ func ConnectConfig(ctx context.Context, connConfig *ConnConfig) (*Conn, error) {
// ParseConfig creates a ConnConfig from a connection string. ParseConfig handles all options that pgconn.ParseConfig
// does. In addition, it accepts the following options:
//
// statement_cache_capacity
// The maximum size of the automatic statement cache. Set to 0 to disable automatic statement caching. Default: 512.
//
// statement_cache_mode
// Possible values: "prepare" and "describe". "prepare" will create prepared statements on the PostgreSQL server.
// "describe" will use the anonymous prepared statement to describe a statement without creating a statement on the
// server. "describe" is primarily useful when the environment does not allow prepared statements such as when
// running a connection pooler like PgBouncer. Default: "prepare"
//
// default_query_exec_mode
// Possible values: "cache_statement", "cache_describe", "describe_exec", "exec", and "simple_protocol". See
// QueryExecMode constant documentation for the meaning of these values. Default: "cache_statement".
//
// statement_cache_capacity
// The maximum size of the statement cache used when executing a query with "cache_statement" query exec mode.
// Default: 512.
//
// description_cache_capacity
// The maximum size of the description cache used when executing a query with "cache_describe" query exec mode.
// Default: 512.
func ParseConfig(connString string) (*ConnConfig, error) {
config, err := pgconn.ParseConfig(connString)
if err != nil {
return nil, err
}
var buildStatementCache BuildStatementCacheFunc
statementCacheCapacity := 512
statementCacheMode := stmtcache.ModePrepare
if s, ok := config.RuntimeParams["statement_cache_capacity"]; ok {
delete(config.RuntimeParams, "statement_cache_capacity")
n, err := strconv.ParseInt(s, 10, 32)
@ -145,22 +144,14 @@ func ParseConfig(connString string) (*ConnConfig, error) {
statementCacheCapacity = int(n)
}
if s, ok := config.RuntimeParams["statement_cache_mode"]; ok {
delete(config.RuntimeParams, "statement_cache_mode")
switch s {
case "prepare":
statementCacheMode = stmtcache.ModePrepare
case "describe":
statementCacheMode = stmtcache.ModeDescribe
default:
return nil, fmt.Errorf("invalid statement_cache_mod: %s", s)
}
}
if statementCacheCapacity > 0 {
buildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, statementCacheMode, statementCacheCapacity)
descriptionCacheCapacity := 512
if s, ok := config.RuntimeParams["description_cache_capacity"]; ok {
delete(config.RuntimeParams, "description_cache_capacity")
n, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return nil, fmt.Errorf("cannot parse description_cache_capacity: %w", err)
}
descriptionCacheCapacity = int(n)
}
defaultQueryExecMode := QueryExecModeCacheStatement
@ -183,12 +174,13 @@ func ParseConfig(connString string) (*ConnConfig, error) {
}
connConfig := &ConnConfig{
Config: *config,
createdByParseConfig: true,
LogLevel: LogLevelInfo,
BuildStatementCache: buildStatementCache,
DefaultQueryExecMode: defaultQueryExecMode,
connString: connString,
Config: *config,
createdByParseConfig: true,
LogLevel: LogLevelInfo,
StatementCacheCapacity: statementCacheCapacity,
DescriptionCacheCapacity: descriptionCacheCapacity,
DefaultQueryExecMode: defaultQueryExecMode,
connString: connString,
}
return connConfig, nil
@ -241,8 +233,12 @@ func connect(ctx context.Context, config *ConnConfig) (c *Conn, err error) {
c.closedChan = make(chan error)
c.wbuf = make([]byte, 0, 1024)
if c.config.BuildStatementCache != nil {
c.stmtcache = c.config.BuildStatementCache(c.pgConn)
if c.config.StatementCacheCapacity > 0 {
c.statementCache = stmtcache.New(c.pgConn, stmtcache.ModePrepare, c.config.StatementCacheCapacity)
}
if c.config.DescriptionCacheCapacity > 0 {
c.descriptionCache = stmtcache.New(c.pgConn, stmtcache.ModeDescribe, c.config.DescriptionCacheCapacity)
}
// Replication connections can't execute the queries to
@ -434,13 +430,13 @@ optionLoop:
return c.execSimpleProtocol(ctx, sql, arguments)
}
if c.stmtcache != nil {
sd, err := c.stmtcache.Get(ctx, sql)
if c.statementCache != nil {
sd, err := c.statementCache.Get(ctx, sql)
if err != nil {
return pgconn.CommandTag{}, err
}
if c.stmtcache.Mode() == stmtcache.ModeDescribe {
if c.statementCache.Mode() == stmtcache.ModeDescribe {
return c.execParams(ctx, sd, arguments)
}
return c.execPrepared(ctx, sd, arguments)
@ -651,8 +647,8 @@ optionLoop:
c.eqb.Reset()
if !ok {
if c.stmtcache != nil {
sd, err = c.stmtcache.Get(ctx, sql)
if c.statementCache != nil {
sd, err = c.statementCache.Get(ctx, sql)
if err != nil {
rows.fatal(err)
return rows, rows.err
@ -697,7 +693,7 @@ optionLoop:
resultFormats = c.eqb.resultFormats
}
if c.stmtcache != nil && c.stmtcache.Mode() == stmtcache.ModeDescribe {
if c.statementCache != nil && c.statementCache.Mode() == stmtcache.ModeDescribe {
rows.resultReader = c.pgConn.ExecParams(ctx, sql, c.eqb.paramValues, sd.ParamOIDs, c.eqb.paramFormats, resultFormats)
} else {
rows.resultReader = c.pgConn.ExecPrepared(ctx, sd.Name, c.eqb.paramValues, c.eqb.paramFormats, resultFormats)
@ -796,8 +792,8 @@ func (c *Conn) SendBatch(ctx context.Context, b *Batch) BatchResults {
var stmtCache stmtcache.Cache
if len(distinctUnpreparedQueries) > 0 {
if c.stmtcache != nil && c.stmtcache.Cap() >= len(distinctUnpreparedQueries) {
stmtCache = c.stmtcache
if c.statementCache != nil && c.statementCache.Cap() >= len(distinctUnpreparedQueries) {
stmtCache = c.statementCache
} else {
stmtCache = stmtcache.New(c.pgConn, stmtcache.ModeDescribe, len(distinctUnpreparedQueries))
}

View File

@ -9,7 +9,6 @@ import (
"time"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/internal/stmtcache"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgtype"
"github.com/stretchr/testify/assert"
@ -137,31 +136,42 @@ func TestParseConfigExtractsStatementCacheOptions(t *testing.T) {
config, err := pgx.ParseConfig("statement_cache_capacity=0")
require.NoError(t, err)
require.Nil(t, config.BuildStatementCache)
require.EqualValues(t, 0, config.StatementCacheCapacity)
config, err = pgx.ParseConfig("statement_cache_capacity=42")
require.NoError(t, err)
require.NotNil(t, config.BuildStatementCache)
c := config.BuildStatementCache(nil)
require.NotNil(t, c)
require.Equal(t, 42, c.Cap())
require.Equal(t, stmtcache.ModePrepare, c.Mode())
require.EqualValues(t, 42, config.StatementCacheCapacity)
config, err = pgx.ParseConfig("statement_cache_capacity=42 statement_cache_mode=prepare")
config, err = pgx.ParseConfig("description_cache_capacity=0")
require.NoError(t, err)
require.NotNil(t, config.BuildStatementCache)
c = config.BuildStatementCache(nil)
require.NotNil(t, c)
require.Equal(t, 42, c.Cap())
require.Equal(t, stmtcache.ModePrepare, c.Mode())
require.EqualValues(t, 0, config.DescriptionCacheCapacity)
config, err = pgx.ParseConfig("statement_cache_capacity=42 statement_cache_mode=describe")
config, err = pgx.ParseConfig("description_cache_capacity=42")
require.NoError(t, err)
require.NotNil(t, config.BuildStatementCache)
c = config.BuildStatementCache(nil)
require.NotNil(t, c)
require.Equal(t, 42, c.Cap())
require.Equal(t, stmtcache.ModeDescribe, c.Mode())
require.EqualValues(t, 42, config.DescriptionCacheCapacity)
// default_query_exec_mode
// Possible values: "cache_statement", "cache_describe", "describe_exec", "exec", and "simple_protocol". See
config, err = pgx.ParseConfig("default_query_exec_mode=cache_statement")
require.NoError(t, err)
require.Equal(t, pgx.QueryExecModeCacheStatement, config.DefaultQueryExecMode)
config, err = pgx.ParseConfig("default_query_exec_mode=cache_describe")
require.NoError(t, err)
require.Equal(t, pgx.QueryExecModeCacheDescribe, config.DefaultQueryExecMode)
config, err = pgx.ParseConfig("default_query_exec_mode=describe_exec")
require.NoError(t, err)
require.Equal(t, pgx.QueryExecModeDescribeExec, config.DefaultQueryExecMode)
config, err = pgx.ParseConfig("default_query_exec_mode=exec")
require.NoError(t, err)
require.Equal(t, pgx.QueryExecModeExec, config.DefaultQueryExecMode)
config, err = pgx.ParseConfig("default_query_exec_mode=simple_protocol")
require.NoError(t, err)
require.Equal(t, pgx.QueryExecModeSimpleProtocol, config.DefaultQueryExecMode)
}
func TestParseConfigExtractsDefaultQueryExecMode(t *testing.T) {
@ -316,56 +326,6 @@ func TestExecFailureCloseBefore(t *testing.T) {
assert.True(t, pgconn.SafeToRetry(err))
}
func TestExecStatementCacheModes(t *testing.T) {
t.Parallel()
config := mustParseConfig(t, os.Getenv("PGX_TEST_DATABASE"))
tests := []struct {
name string
buildStatementCache pgx.BuildStatementCacheFunc
}{
{
name: "disabled",
buildStatementCache: nil,
},
{
name: "prepare",
buildStatementCache: func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModePrepare, 32)
},
},
{
name: "describe",
buildStatementCache: func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModeDescribe, 32)
},
},
}
for _, tt := range tests {
func() {
config.BuildStatementCache = tt.buildStatementCache
conn := mustConnect(t, config)
defer closeConn(t, conn)
commandTag, err := conn.Exec(context.Background(), "select 1")
assert.NoError(t, err, tt.name)
assert.Equal(t, "SELECT 1", commandTag.String(), tt.name)
commandTag, err = conn.Exec(context.Background(), "select 1 union all select 1")
assert.NoError(t, err, tt.name)
assert.Equal(t, "SELECT 2", commandTag.String(), tt.name)
commandTag, err = conn.Exec(context.Background(), "select 1")
assert.NoError(t, err, tt.name)
assert.Equal(t, "SELECT 1", commandTag.String(), tt.name)
ensureConnValid(t, conn)
}()
}
}
func TestExecPerQuerySimpleProtocol(t *testing.T) {
t.Parallel()

View File

@ -118,10 +118,9 @@ func assertConfigsEqual(t *testing.T, expected, actual *pgx.ConnConfig, testName
assert.Equalf(t, expected.Logger, actual.Logger, "%s - Logger", testName)
assert.Equalf(t, expected.LogLevel, actual.LogLevel, "%s - LogLevel", testName)
assert.Equalf(t, expected.ConnString(), actual.ConnString(), "%s - ConnString", testName)
// Can't test function equality, so just test that they are set or not.
assert.Equalf(t, expected.BuildStatementCache == nil, actual.BuildStatementCache == nil, "%s - BuildStatementCache", testName)
assert.Equalf(t, expected.StatementCacheCapacity, actual.StatementCacheCapacity, "%s - StatementCacheCapacity", testName)
assert.Equalf(t, expected.DescriptionCacheCapacity, actual.DescriptionCacheCapacity, "%s - DescriptionCacheCapacity", testName)
assert.Equalf(t, expected.DefaultQueryExecMode, actual.DefaultQueryExecMode, "%s - DefaultQueryExecMode", testName)
assert.Equalf(t, expected.Host, actual.Host, "%s - Host", testName)
assert.Equalf(t, expected.Database, actual.Database, "%s - Database", testName)
assert.Equalf(t, expected.Port, actual.Port, "%s - Port", testName)

View File

@ -6,8 +6,6 @@ import (
"testing"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/internal/stmtcache"
"github.com/jackc/pgx/v5/pgconn"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -19,9 +17,8 @@ func TestPgbouncerStatementCacheDescribe(t *testing.T) {
}
config := mustParseConfig(t, connString)
config.BuildStatementCache = func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModeDescribe, 1024)
}
config.DefaultQueryExecMode = pgx.QueryExecModeCacheDescribe
config.DescriptionCacheCapacity = 1024
testPgbouncer(t, config, 10, 100)
}
@ -33,7 +30,6 @@ func TestPgbouncerSimpleProtocol(t *testing.T) {
}
config := mustParseConfig(t, connString)
config.BuildStatementCache = nil
config.DefaultQueryExecMode = pgx.QueryExecModeSimpleProtocol
testPgbouncer(t, config, 10, 100)

View File

@ -164,12 +164,10 @@ func assertConnConfigsEqual(t *testing.T, expected, actual *pgx.ConnConfig, test
assert.Equalf(t, expected.Logger, actual.Logger, "%s - Logger", testName)
assert.Equalf(t, expected.LogLevel, actual.LogLevel, "%s - LogLevel", testName)
assert.Equalf(t, expected.ConnString(), actual.ConnString(), "%s - ConnString", testName)
// Can't test function equality, so just test that they are set or not.
assert.Equalf(t, expected.BuildStatementCache == nil, actual.BuildStatementCache == nil, "%s - BuildStatementCache", testName)
assert.Equalf(t, expected.StatementCacheCapacity, actual.StatementCacheCapacity, "%s - StatementCacheCapacity", testName)
assert.Equalf(t, expected.DescriptionCacheCapacity, actual.DescriptionCacheCapacity, "%s - DescriptionCacheCapacity", testName)
assert.Equalf(t, expected.DefaultQueryExecMode, actual.DefaultQueryExecMode, "%s - DefaultQueryExecMode", testName)
assert.Equalf(t, expected.DefaultQueryExecMode, actual.DefaultQueryExecMode, "%s - DefaultQueryExecMode", testName)
assert.Equalf(t, expected.Host, actual.Host, "%s - Host", testName)
assert.Equalf(t, expected.Database, actual.Database, "%s - Database", testName)
assert.Equalf(t, expected.Port, actual.Port, "%s - Port", testName)

View File

@ -13,7 +13,6 @@ import (
"time"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/internal/stmtcache"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgtype"
"github.com/stretchr/testify/assert"
@ -1827,63 +1826,14 @@ func TestConnSimpleProtocolRefusesNonStandardConformingStrings(t *testing.T) {
ensureConnValid(t, conn)
}
func TestQueryStatementCacheModes(t *testing.T) {
t.Parallel()
config := mustParseConfig(t, os.Getenv("PGX_TEST_DATABASE"))
tests := []struct {
name string
buildStatementCache pgx.BuildStatementCacheFunc
}{
{
name: "disabled",
buildStatementCache: nil,
},
{
name: "prepare",
buildStatementCache: func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModePrepare, 32)
},
},
{
name: "describe",
buildStatementCache: func(conn *pgconn.PgConn) stmtcache.Cache {
return stmtcache.New(conn, stmtcache.ModeDescribe, 32)
},
},
}
for _, tt := range tests {
func() {
config.BuildStatementCache = tt.buildStatementCache
conn := mustConnect(t, config)
defer closeConn(t, conn)
var n int
err := conn.QueryRow(context.Background(), "select 1").Scan(&n)
assert.NoError(t, err, tt.name)
assert.Equal(t, 1, n, tt.name)
err = conn.QueryRow(context.Background(), "select 2").Scan(&n)
assert.NoError(t, err, tt.name)
assert.Equal(t, 2, n, tt.name)
err = conn.QueryRow(context.Background(), "select 1").Scan(&n)
assert.NoError(t, err, tt.name)
assert.Equal(t, 1, n, tt.name)
ensureConnValid(t, conn)
}()
}
}
// https://github.com/jackc/pgx/issues/895
func TestQueryErrorWithNilStatementCacheMode(t *testing.T) {
func TestQueryErrorWithDisabledStatementCache(t *testing.T) {
t.Parallel()
config := mustParseConfig(t, os.Getenv("PGX_TEST_DATABASE"))
config.BuildStatementCache = nil
config.DefaultQueryExecMode = pgx.QueryExecModeDescribeExec
config.StatementCacheCapacity = 0
config.DescriptionCacheCapacity = 0
conn := mustConnect(t, config)
defer closeConn(t, conn)

View File

@ -161,8 +161,8 @@ func (rows *connRows) Close() {
if rows.logger.shouldLog(LogLevelError) {
rows.logger.log(rows.ctx, LogLevelError, "Query", map[string]interface{}{"err": rows.err, "sql": rows.sql, "args": logQueryArgs(rows.args)})
}
if rows.err != nil && rows.conn.stmtcache != nil {
rows.conn.stmtcache.StatementErrored(rows.sql, rows.err)
if rows.err != nil && rows.conn.statementCache != nil {
rows.conn.statementCache.StatementErrored(rows.sql, rows.err)
}
}
}