Replace DSN with keyword/value in comments and documentation

The term DSN is not used in the PostgreSQL documentation. I'm not sure
why it was originally used. Use the correct PostgreSQL terminology.
This commit is contained in:
Jack Christensen 2024-05-11 14:33:35 -05:00
parent cf50c60869
commit a966716860
10 changed files with 46 additions and 44 deletions

11
doc.go
View File

@ -11,9 +11,10 @@ The primary way of establishing a connection is with [pgx.Connect]:
conn, err := pgx.Connect(context.Background(), os.Getenv("DATABASE_URL")) conn, err := pgx.Connect(context.Background(), os.Getenv("DATABASE_URL"))
The database connection string can be in URL or DSN format. Both PostgreSQL settings and pgx settings can be specified The database connection string can be in URL or key/value format. Both PostgreSQL settings and pgx settings can be
here. In addition, a config struct can be created by [ParseConfig] and modified before establishing the connection with specified here. In addition, a config struct can be created by [ParseConfig] and modified before establishing the
[ConnectConfig] to configure settings such as tracing that cannot be configured with a connection string. connection with [ConnectConfig] to configure settings such as tracing that cannot be configured with a connection
string.
Connection Pool Connection Pool
@ -23,8 +24,8 @@ github.com/jackc/pgx/v5/pgxpool for a concurrency safe connection pool.
Query Interface Query Interface
pgx implements Query in the familiar database/sql style. However, pgx provides generic functions such as CollectRows and pgx implements Query in the familiar database/sql style. However, pgx provides generic functions such as CollectRows and
ForEachRow that are a simpler and safer way of processing rows than manually calling defer rows.Close(), rows.Next(), rows.Scan, and ForEachRow that are a simpler and safer way of processing rows than manually calling defer rows.Close(), rows.Next(),
rows.Err(). rows.Scan, and rows.Err().
CollectRows can be used collect all returned rows into a slice. CollectRows can be used collect all returned rows into a slice.

View File

@ -160,11 +160,11 @@ func NetworkAddress(host string, port uint16) (network, address string) {
// ParseConfig builds a *Config from connString with similar behavior to the PostgreSQL standard C library libpq. It // ParseConfig builds a *Config from connString with similar behavior to the PostgreSQL standard C library libpq. It
// uses the same defaults as libpq (e.g. port=5432) and understands most PG* environment variables. ParseConfig closely // uses the same defaults as libpq (e.g. port=5432) and understands most PG* environment variables. ParseConfig closely
// matches the parsing behavior of libpq. connString may either be in URL format or keyword = value format (DSN style). // matches the parsing behavior of libpq. connString may either be in URL format or keyword = value format. See
// See https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING for details. connString also may be // https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING for details. connString also may be empty
// empty to only read from the environment. If a password is not supplied it will attempt to read the .pgpass file. // to only read from the environment. If a password is not supplied it will attempt to read the .pgpass file.
// //
// # Example DSN // # Example Keyword/Value
// user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca // user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca
// //
// # Example URL // # Example URL
@ -183,7 +183,7 @@ func NetworkAddress(host string, port uint16) (network, address string) {
// postgres://jack:secret@foo.example.com:5432,bar.example.com:5432/mydb // postgres://jack:secret@foo.example.com:5432,bar.example.com:5432/mydb
// //
// ParseConfig currently recognizes the following environment variable and their parameter key word equivalents passed // ParseConfig currently recognizes the following environment variable and their parameter key word equivalents passed
// via database URL or DSN: // via database URL or keyword/value:
// //
// PGHOST // PGHOST
// PGPORT // PGPORT
@ -247,16 +247,16 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
connStringSettings := make(map[string]string) connStringSettings := make(map[string]string)
if connString != "" { if connString != "" {
var err error var err error
// connString may be a database URL or a DSN // connString may be a database URL or in PostgreSQL keyword/value format
if strings.HasPrefix(connString, "postgres://") || strings.HasPrefix(connString, "postgresql://") { if strings.HasPrefix(connString, "postgres://") || strings.HasPrefix(connString, "postgresql://") {
connStringSettings, err = parseURLSettings(connString) connStringSettings, err = parseURLSettings(connString)
if err != nil { if err != nil {
return nil, &ParseConfigError{ConnString: connString, msg: "failed to parse as URL", err: err} return nil, &ParseConfigError{ConnString: connString, msg: "failed to parse as URL", err: err}
} }
} else { } else {
connStringSettings, err = parseDSNSettings(connString) connStringSettings, err = parseKeywordValueSettings(connString)
if err != nil { if err != nil {
return nil, &ParseConfigError{ConnString: connString, msg: "failed to parse as DSN", err: err} return nil, &ParseConfigError{ConnString: connString, msg: "failed to parse as keyword/value", err: err}
} }
} }
} }
@ -534,7 +534,7 @@ func isIPOnly(host string) bool {
var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1} var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1}
func parseDSNSettings(s string) (map[string]string, error) { func parseKeywordValueSettings(s string) (map[string]string, error) {
settings := make(map[string]string) settings := make(map[string]string)
nameMap := map[string]string{ nameMap := map[string]string{
@ -545,7 +545,7 @@ func parseDSNSettings(s string) (map[string]string, error) {
var key, val string var key, val string
eqIdx := strings.IndexRune(s, '=') eqIdx := strings.IndexRune(s, '=')
if eqIdx < 0 { if eqIdx < 0 {
return nil, errors.New("invalid dsn") return nil, errors.New("invalid keyword/value")
} }
key = strings.Trim(s[:eqIdx], " \t\n\r\v\f") key = strings.Trim(s[:eqIdx], " \t\n\r\v\f")
@ -597,7 +597,7 @@ func parseDSNSettings(s string) (map[string]string, error) {
} }
if key == "" { if key == "" {
return nil, errors.New("invalid dsn") return nil, errors.New("invalid keyword/value")
} }
settings[key] = val settings[key] = val

View File

@ -336,7 +336,7 @@ func TestParseConfig(t *testing.T) {
}, },
}, },
{ {
name: "DSN everything", name: "Key/value everything",
connString: "user=jack password=secret host=localhost port=5432 dbname=mydb sslmode=disable application_name=pgxtest search_path=myschema connect_timeout=5", connString: "user=jack password=secret host=localhost port=5432 dbname=mydb sslmode=disable application_name=pgxtest search_path=myschema connect_timeout=5",
config: &pgconn.Config{ config: &pgconn.Config{
User: "jack", User: "jack",
@ -353,7 +353,7 @@ func TestParseConfig(t *testing.T) {
}, },
}, },
{ {
name: "DSN with escaped single quote", name: "Key/value with escaped single quote",
connString: "user=jack\\'s password=secret host=localhost port=5432 dbname=mydb sslmode=disable", connString: "user=jack\\'s password=secret host=localhost port=5432 dbname=mydb sslmode=disable",
config: &pgconn.Config{ config: &pgconn.Config{
User: "jack's", User: "jack's",
@ -366,7 +366,7 @@ func TestParseConfig(t *testing.T) {
}, },
}, },
{ {
name: "DSN with escaped backslash", name: "Key/value with escaped backslash",
connString: "user=jack password=sooper\\\\secret host=localhost port=5432 dbname=mydb sslmode=disable", connString: "user=jack password=sooper\\\\secret host=localhost port=5432 dbname=mydb sslmode=disable",
config: &pgconn.Config{ config: &pgconn.Config{
User: "jack", User: "jack",
@ -379,7 +379,7 @@ func TestParseConfig(t *testing.T) {
}, },
}, },
{ {
name: "DSN with single quoted values", name: "Key/value with single quoted values",
connString: "user='jack' host='localhost' dbname='mydb' sslmode='disable'", connString: "user='jack' host='localhost' dbname='mydb' sslmode='disable'",
config: &pgconn.Config{ config: &pgconn.Config{
User: "jack", User: "jack",
@ -391,7 +391,7 @@ func TestParseConfig(t *testing.T) {
}, },
}, },
{ {
name: "DSN with single quoted value with escaped single quote", name: "Key/value with single quoted value with escaped single quote",
connString: "user='jack\\'s' host='localhost' dbname='mydb' sslmode='disable'", connString: "user='jack\\'s' host='localhost' dbname='mydb' sslmode='disable'",
config: &pgconn.Config{ config: &pgconn.Config{
User: "jack's", User: "jack's",
@ -403,7 +403,7 @@ func TestParseConfig(t *testing.T) {
}, },
}, },
{ {
name: "DSN with empty single quoted value", name: "Key/value with empty single quoted value",
connString: "user='jack' password='' host='localhost' dbname='mydb' sslmode='disable'", connString: "user='jack' password='' host='localhost' dbname='mydb' sslmode='disable'",
config: &pgconn.Config{ config: &pgconn.Config{
User: "jack", User: "jack",
@ -415,7 +415,7 @@ func TestParseConfig(t *testing.T) {
}, },
}, },
{ {
name: "DSN with space between key and value", name: "Key/value with space between key and value",
connString: "user = 'jack' password = '' host = 'localhost' dbname = 'mydb' sslmode='disable'", connString: "user = 'jack' password = '' host = 'localhost' dbname = 'mydb' sslmode='disable'",
config: &pgconn.Config{ config: &pgconn.Config{
User: "jack", User: "jack",
@ -491,7 +491,7 @@ func TestParseConfig(t *testing.T) {
}, },
}, },
{ {
name: "DSN multiple hosts one port", name: "Key/value multiple hosts one port",
connString: "user=jack password=secret host=foo,bar,baz port=5432 dbname=mydb sslmode=disable", connString: "user=jack password=secret host=foo,bar,baz port=5432 dbname=mydb sslmode=disable",
config: &pgconn.Config{ config: &pgconn.Config{
User: "jack", User: "jack",
@ -516,7 +516,7 @@ func TestParseConfig(t *testing.T) {
}, },
}, },
{ {
name: "DSN multiple hosts multiple ports", name: "Key/value multiple hosts multiple ports",
connString: "user=jack password=secret host=foo,bar,baz port=1,2,3 dbname=mydb sslmode=disable", connString: "user=jack password=secret host=foo,bar,baz port=1,2,3 dbname=mydb sslmode=disable",
config: &pgconn.Config{ config: &pgconn.Config{
User: "jack", User: "jack",
@ -772,18 +772,18 @@ func TestParseConfig(t *testing.T) {
} }
// https://github.com/jackc/pgconn/issues/47 // https://github.com/jackc/pgconn/issues/47
func TestParseConfigDSNWithTrailingEmptyEqualDoesNotPanic(t *testing.T) { func TestParseConfigKVWithTrailingEmptyEqualDoesNotPanic(t *testing.T) {
_, err := pgconn.ParseConfig("host= user= password= port= database=") _, err := pgconn.ParseConfig("host= user= password= port= database=")
require.NoError(t, err) require.NoError(t, err)
} }
func TestParseConfigDSNLeadingEqual(t *testing.T) { func TestParseConfigKVLeadingEqual(t *testing.T) {
_, err := pgconn.ParseConfig("= user=jack") _, err := pgconn.ParseConfig("= user=jack")
require.Error(t, err) require.Error(t, err)
} }
// https://github.com/jackc/pgconn/issues/49 // https://github.com/jackc/pgconn/issues/49
func TestParseConfigDSNTrailingBackslash(t *testing.T) { func TestParseConfigKVTrailingBackslash(t *testing.T) {
_, err := pgconn.ParseConfig(`x=x\`) _, err := pgconn.ParseConfig(`x=x\`)
require.Error(t, err) require.Error(t, err)
assert.Contains(t, err.Error(), "invalid backslash") assert.Contains(t, err.Error(), "invalid backslash")

View File

@ -5,8 +5,8 @@ nearly the same level is the C library libpq.
Establishing a Connection Establishing a Connection
Use Connect to establish a connection. It accepts a connection string in URL or DSN and will read the environment for Use Connect to establish a connection. It accepts a connection string in URL or keyword/value format and will read the
libpq style environment variables. environment for libpq style environment variables.
Executing a Query Executing a Query

View File

@ -211,10 +211,10 @@ func redactPW(connString string) string {
return redactURL(u) return redactURL(u)
} }
} }
quotedDSN := regexp.MustCompile(`password='[^']*'`) quotedKV := regexp.MustCompile(`password='[^']*'`)
connString = quotedDSN.ReplaceAllLiteralString(connString, "password=xxxxx") connString = quotedKV.ReplaceAllLiteralString(connString, "password=xxxxx")
plainDSN := regexp.MustCompile(`password=[^ ]*`) plainKV := regexp.MustCompile(`password=[^ ]*`)
connString = plainDSN.ReplaceAllLiteralString(connString, "password=xxxxx") connString = plainKV.ReplaceAllLiteralString(connString, "password=xxxxx")
brokenURL := regexp.MustCompile(`:[^:@]+?@`) brokenURL := regexp.MustCompile(`:[^:@]+?@`)
connString = brokenURL.ReplaceAllLiteralString(connString, ":xxxxxx@") connString = brokenURL.ReplaceAllLiteralString(connString, ":xxxxxx@")
return connString return connString

View File

@ -19,12 +19,12 @@ func TestConfigError(t *testing.T) {
expectedMsg: "cannot parse `postgresql://foo:xxxxx@host`: msg", expectedMsg: "cannot parse `postgresql://foo:xxxxx@host`: msg",
}, },
{ {
name: "dsn with password unquoted", name: "keyword/value with password unquoted",
err: pgconn.NewParseConfigError("host=host password=password user=user", "msg", nil), err: pgconn.NewParseConfigError("host=host password=password user=user", "msg", nil),
expectedMsg: "cannot parse `host=host password=xxxxx user=user`: msg", expectedMsg: "cannot parse `host=host password=xxxxx user=user`: msg",
}, },
{ {
name: "dsn with password quoted", name: "keyword/value with password quoted",
err: pgconn.NewParseConfigError("host=host password='pass word' user=user", "msg", nil), err: pgconn.NewParseConfigError("host=host password='pass word' user=user", "msg", nil),
expectedMsg: "cannot parse `host=host password=xxxxx user=user`: msg", expectedMsg: "cannot parse `host=host password=xxxxx user=user`: msg",
}, },

View File

@ -105,8 +105,9 @@ type PgConn struct {
cleanupDone chan struct{} cleanupDone chan struct{}
} }
// Connect establishes a connection to a PostgreSQL server using the environment and connString (in URL or DSN format) // Connect establishes a connection to a PostgreSQL server using the environment and connString (in URL or keyword/value
// to provide configuration. See documentation for [ParseConfig] for details. ctx can be used to cancel a connect attempt. // format) to provide configuration. See documentation for [ParseConfig] for details. ctx can be used to cancel a
// connect attempt.
func Connect(ctx context.Context, connString string) (*PgConn, error) { func Connect(ctx context.Context, connString string) (*PgConn, error) {
config, err := ParseConfig(connString) config, err := ParseConfig(connString)
if err != nil { if err != nil {
@ -116,9 +117,9 @@ func Connect(ctx context.Context, connString string) (*PgConn, error) {
return ConnectConfig(ctx, config) return ConnectConfig(ctx, config)
} }
// Connect establishes a connection to a PostgreSQL server using the environment and connString (in URL or DSN format) // Connect establishes a connection to a PostgreSQL server using the environment and connString (in URL or keyword/value
// and ParseConfigOptions to provide additional configuration. See documentation for [ParseConfig] for details. ctx can be // format) and ParseConfigOptions to provide additional configuration. See documentation for [ParseConfig] for details.
// used to cancel a connect attempt. // ctx can be used to cancel a connect attempt.
func ConnectWithOptions(ctx context.Context, connString string, parseConfigOptions ParseConfigOptions) (*PgConn, error) { func ConnectWithOptions(ctx context.Context, connString string, parseConfigOptions ParseConfigOptions) (*PgConn, error) {
config, err := ParseConfigWithOptions(connString, parseConfigOptions) config, err := ParseConfigWithOptions(connString, parseConfigOptions)
if err != nil { if err != nil {

View File

@ -8,7 +8,7 @@ The primary way of creating a pool is with [pgxpool.New]:
pool, err := pgxpool.New(context.Background(), os.Getenv("DATABASE_URL")) pool, err := pgxpool.New(context.Background(), os.Getenv("DATABASE_URL"))
The database connection string can be in URL or DSN format. PostgreSQL settings, pgx settings, and pool settings can be The database connection string can be in URL or keyword/value format. PostgreSQL settings, pgx settings, and pool settings can be
specified here. In addition, a config struct can be created by [ParseConfig]. specified here. In addition, a config struct can be created by [ParseConfig].
config, err := pgxpool.ParseConfig(os.Getenv("DATABASE_URL")) config, err := pgxpool.ParseConfig(os.Getenv("DATABASE_URL"))

View File

@ -279,7 +279,7 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
// //
// See Config for definitions of these arguments. // See Config for definitions of these arguments.
// //
// # Example DSN // # Example Keyword/Value
// user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10 // user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10
// //
// # Example URL // # Example URL

View File

@ -7,7 +7,7 @@
// return err // return err
// } // }
// //
// Or from a DSN string. // Or from a keyword/value string.
// //
// db, err := sql.Open("pgx", "user=postgres password=secret host=localhost port=5432 database=pgx_test sslmode=disable") // db, err := sql.Open("pgx", "user=postgres password=secret host=localhost port=5432 database=pgx_test sslmode=disable")
// if err != nil { // if err != nil {