mirror of
https://github.com/TECHNOFAB11/dbmate.git
synced 2026-02-02 17:35:08 +01:00
Add postgres support for socket parameter (#136)
Simplifies connecting to postgres via sockets (https://github.com/amacneil/dbmate/issues/107), and standardize the `socket` parameter across both mysql and postgresql. Closes #107
This commit is contained in:
parent
45a122eb86
commit
ed9e57a4ad
4 changed files with 98 additions and 3 deletions
|
|
@ -127,7 +127,7 @@ protocol://username:password@host:port/database_name?options
|
||||||
DATABASE_URL="mysql://username:password@127.0.0.1:3306/database_name"
|
DATABASE_URL="mysql://username:password@127.0.0.1:3306/database_name"
|
||||||
```
|
```
|
||||||
|
|
||||||
A socket parameter can be specified to connect through a unix socket file:
|
A `socket` parameter can be specified to connect through a unix socket:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
DATABASE_URL="mysql://username:password@/database_name?socket=/var/run/mysqld/mysqld.sock"
|
DATABASE_URL="mysql://username:password@/database_name?socket=/var/run/mysqld/mysqld.sock"
|
||||||
|
|
@ -141,6 +141,12 @@ When connecting to Postgres, you may need to add the `sslmode=disable` option to
|
||||||
DATABASE_URL="postgres://username:password@127.0.0.1:5432/database_name?sslmode=disable"
|
DATABASE_URL="postgres://username:password@127.0.0.1:5432/database_name?sslmode=disable"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
A `socket` or `host` parameter can be specified to connect through a unix socket (note: specify the directory only):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
DATABASE_URL="postgres://username:password@/database_name?socket=/var/run/postgresql"
|
||||||
|
```
|
||||||
|
|
||||||
**SQLite**
|
**SQLite**
|
||||||
|
|
||||||
SQLite databases are stored on the filesystem, so you do not need to specify a host. By default, files are relative to the current directory. For example, the following will create a database at `./db/database_name.sqlite3`:
|
SQLite databases are stored on the filesystem, so you do not need to specify a host. By default, files are relative to the current directory. For example, the following will create a database at `./db/database_name.sqlite3`:
|
||||||
|
|
|
||||||
|
|
@ -62,12 +62,20 @@ func TestNormalizeMySQLURLCustomSpecialChars(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNormalizeMySQLURLSocket(t *testing.T) {
|
func TestNormalizeMySQLURLSocket(t *testing.T) {
|
||||||
|
// test with no user/pass
|
||||||
u, err := url.Parse("mysql:///foo?socket=/var/run/mysqld/mysqld.sock&flag=on")
|
u, err := url.Parse("mysql:///foo?socket=/var/run/mysqld/mysqld.sock&flag=on")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "", u.Host)
|
require.Equal(t, "", u.Host)
|
||||||
|
|
||||||
s := normalizeMySQLURL(u)
|
s := normalizeMySQLURL(u)
|
||||||
require.Equal(t, "unix(/var/run/mysqld/mysqld.sock)/foo?flag=on&multiStatements=true", s)
|
require.Equal(t, "unix(/var/run/mysqld/mysqld.sock)/foo?flag=on&multiStatements=true", s)
|
||||||
|
|
||||||
|
// test with user/pass
|
||||||
|
u, err = url.Parse("mysql://bob:secret@fakehost/foo?socket=/var/run/mysqld/mysqld.sock&flag=on")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
s = normalizeMySQLURL(u)
|
||||||
|
require.Equal(t, "bob:secret@unix(/var/run/mysqld/mysqld.sock)/foo?flag=on&multiStatements=true", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMySQLCreateDropDatabase(t *testing.T) {
|
func TestMySQLCreateDropDatabase(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,47 @@ func init() {
|
||||||
type PostgresDriver struct {
|
type PostgresDriver struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalizePostgresURL(u *url.URL) string {
|
||||||
|
hostname := u.Hostname()
|
||||||
|
port := u.Port()
|
||||||
|
query := u.Query()
|
||||||
|
|
||||||
|
// support socket parameter for consistency with mysql
|
||||||
|
if query.Get("socket") != "" {
|
||||||
|
query.Set("host", query.Get("socket"))
|
||||||
|
query.Del("socket")
|
||||||
|
}
|
||||||
|
|
||||||
|
// default hostname
|
||||||
|
if hostname == "" {
|
||||||
|
hostname = "localhost"
|
||||||
|
}
|
||||||
|
|
||||||
|
// host param overrides url hostname
|
||||||
|
if query.Get("host") != "" {
|
||||||
|
hostname = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// always specify a port
|
||||||
|
if query.Get("port") != "" {
|
||||||
|
port = query.Get("port")
|
||||||
|
query.Del("port")
|
||||||
|
}
|
||||||
|
if port == "" {
|
||||||
|
port = "5432"
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate output URL
|
||||||
|
out, _ := url.Parse(u.String())
|
||||||
|
out.Host = fmt.Sprintf("%s:%s", hostname, port)
|
||||||
|
out.RawQuery = query.Encode()
|
||||||
|
|
||||||
|
return out.String()
|
||||||
|
}
|
||||||
|
|
||||||
// Open creates a new database connection
|
// Open creates a new database connection
|
||||||
func (drv PostgresDriver) Open(u *url.URL) (*sql.DB, error) {
|
func (drv PostgresDriver) Open(u *url.URL) (*sql.DB, error) {
|
||||||
return sql.Open("postgres", u.String())
|
return sql.Open("postgres", normalizePostgresURL(u))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (drv PostgresDriver) openPostgresDB(u *url.URL) (*sql.DB, error) {
|
func (drv PostgresDriver) openPostgresDB(u *url.URL) (*sql.DB, error) {
|
||||||
|
|
@ -91,7 +129,7 @@ func postgresSchemaMigrationsDump(db *sql.DB) ([]byte, error) {
|
||||||
func (drv PostgresDriver) DumpSchema(u *url.URL, db *sql.DB) ([]byte, error) {
|
func (drv PostgresDriver) DumpSchema(u *url.URL, db *sql.DB) ([]byte, error) {
|
||||||
// load schema
|
// load schema
|
||||||
schema, err := runCommand("pg_dump", "--format=plain", "--encoding=UTF8",
|
schema, err := runCommand("pg_dump", "--format=plain", "--encoding=UTF8",
|
||||||
"--schema-only", "--no-privileges", "--no-owner", u.String())
|
"--schema-only", "--no-privileges", "--no-owner", normalizePostgresURL(u))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,49 @@ func prepTestPostgresDB(t *testing.T) *sql.DB {
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNormalizePostgresURLDefaults(t *testing.T) {
|
||||||
|
u, err := url.Parse("postgres:///foo")
|
||||||
|
require.NoError(t, err)
|
||||||
|
s := normalizePostgresURL(u)
|
||||||
|
require.Equal(t, "postgres://localhost:5432/foo", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNormalizePostgresURLCustom(t *testing.T) {
|
||||||
|
u, err := url.Parse("postgres://bob:secret@myhost:1234/foo?bar=baz")
|
||||||
|
require.NoError(t, err)
|
||||||
|
s := normalizePostgresURL(u)
|
||||||
|
require.Equal(t, "postgres://bob:secret@myhost:1234/foo?bar=baz", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNormalizePostgresURLHostPortParams(t *testing.T) {
|
||||||
|
u, err := url.Parse("postgres://bob:secret@myhost:1234/foo?port=9999&bar=baz")
|
||||||
|
require.NoError(t, err)
|
||||||
|
s := normalizePostgresURL(u)
|
||||||
|
require.Equal(t, "postgres://bob:secret@myhost:9999/foo?bar=baz", s)
|
||||||
|
|
||||||
|
u, err = url.Parse("postgres://bob:secret@myhost:1234/foo?host=new&port=9999")
|
||||||
|
require.NoError(t, err)
|
||||||
|
s = normalizePostgresURL(u)
|
||||||
|
require.Equal(t, "postgres://bob:secret@:9999/foo?host=new", s)
|
||||||
|
|
||||||
|
u, err = url.Parse("postgres://bob:secret@myhost:1234/foo?host=/var/run/postgresql")
|
||||||
|
require.NoError(t, err)
|
||||||
|
s = normalizePostgresURL(u)
|
||||||
|
require.Equal(t, "postgres://bob:secret@:1234/foo?host=%2Fvar%2Frun%2Fpostgresql", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNormalizePostgresURLSocketParam(t *testing.T) {
|
||||||
|
u, err := url.Parse("postgres://bob:secret@localhost/foo?socket=/var/run/postgresql")
|
||||||
|
require.NoError(t, err)
|
||||||
|
s := normalizePostgresURL(u)
|
||||||
|
require.Equal(t, "postgres://bob:secret@:5432/foo?host=%2Fvar%2Frun%2Fpostgresql", s)
|
||||||
|
|
||||||
|
u, err = url.Parse("postgres:///foo?socket=/var/run/postgresql")
|
||||||
|
require.NoError(t, err)
|
||||||
|
s = normalizePostgresURL(u)
|
||||||
|
require.Equal(t, "postgres://:5432/foo?host=%2Fvar%2Frun%2Fpostgresql", s)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPostgresCreateDropDatabase(t *testing.T) {
|
func TestPostgresCreateDropDatabase(t *testing.T) {
|
||||||
drv := PostgresDriver{}
|
drv := PostgresDriver{}
|
||||||
u := postgresTestURL(t)
|
u := postgresTestURL(t)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue