@@ -14,6 +14,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -282,6 +283,38 @@ func ParseURI(uri string) (ConnConfig, error) {
|
|||||||
return cp, nil
|
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
|
// 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.
|
// for bound parameters. These placeholders are referenced positional as $1, $2, etc.
|
||||||
func (c *Conn) Prepare(name, sql string) (ps *PreparedStatement, err error) {
|
func (c *Conn) Prepare(name, sql string) (ps *PreparedStatement, err error) {
|
||||||
|
|||||||
@@ -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) {
|
func TestExec(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user