From 7e2886c5764854935ef53b1fc9d012e43a21657d Mon Sep 17 00:00:00 2001 From: deoxxa Date: Wed, 8 Apr 2015 14:50:56 +1000 Subject: [PATCH 1/2] add ParseDSN function --- conn.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/conn.go b/conn.go index 580b23cc..dd205f78 100644 --- a/conn.go +++ b/conn.go @@ -14,6 +14,7 @@ import ( "os" "os/user" "path/filepath" + "regexp" "strconv" "strings" "time" @@ -282,6 +283,38 @@ func ParseURI(uri string) (ConnConfig, error) { return cp, nil } +var dsn_regexp = regexp.MustCompile(`([a-z]+)=((?:"[^"]+")|(?:[^ ]+))`) + +// ParseDSN parses a database DSN (data source name) into a ConnConfig +// +// e.g. ParseDSN("user=username password=password host=1.2.3.4 port=5432 dbname=mydb") +func ParseDSN(s string) (ConnConfig, error) { + var cp ConnConfig + + m := dsn_regexp.FindAllStringSubmatch(s, -1) + + for _, b := range m { + switch b[1] { + case "user": + cp.User = b[2] + case "password": + cp.Password = b[2] + case "host": + cp.Host = b[2] + case "port": + if p, err := strconv.ParseUint(b[2], 10, 16); err != nil { + return cp, err + } else { + cp.Port = uint16(p) + } + case "dbname": + cp.Database = b[2] + } + } + + return cp, nil +} + // Prepare creates a prepared statement with name and sql. sql can contain placeholders // for bound parameters. These placeholders are referenced positional as $1, $2, etc. func (c *Conn) Prepare(name, sql string) (ps *PreparedStatement, err error) { From 36d1a58b42fa8d6ebd72519609ae4824c7fcdce2 Mon Sep 17 00:00:00 2001 From: deoxxa Date: Wed, 8 Apr 2015 14:55:15 +1000 Subject: [PATCH 2/2] add tests for ParseDSN --- conn_test.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/conn_test.go b/conn_test.go index 8c6e24cf..5340be62 100644 --- a/conn_test.go +++ b/conn_test.go @@ -255,6 +255,55 @@ func TestParseURI(t *testing.T) { } } +func TestParseDSN(t *testing.T) { + t.Parallel() + + tests := []struct { + url string + connParams pgx.ConnConfig + }{ + { + url: "user=jack password=secret host=localhost port=5432 dbname=mydb", + connParams: pgx.ConnConfig{ + User: "jack", + Password: "secret", + Host: "localhost", + Port: 5432, + Database: "mydb", + }, + }, + { + url: "user=jack host=localhost port=5432 dbname=mydb", + connParams: pgx.ConnConfig{ + User: "jack", + Host: "localhost", + Port: 5432, + Database: "mydb", + }, + }, + { + url: "user=jack host=localhost dbname=mydb", + connParams: pgx.ConnConfig{ + User: "jack", + Host: "localhost", + Database: "mydb", + }, + }, + } + + for i, tt := range tests { + connParams, err := pgx.ParseDSN(tt.url) + if err != nil { + t.Errorf("%d. Unexpected error from pgx.ParseDSN(%q) => %v", i, tt.url, err) + continue + } + + if connParams != tt.connParams { + t.Errorf("%d. expected %#v got %#v", i, tt.connParams, connParams) + } + } +} + func TestExec(t *testing.T) { t.Parallel()