mirror of https://github.com/pressly/goose.git
parent
9024628f79
commit
f13ed7399e
5
Makefile
5
Makefile
|
@ -42,7 +42,7 @@ test-packages:
|
|||
test-packages-short:
|
||||
go test -test.short $(GO_TEST_FLAGS) $$(go list ./... | grep -v -e /tests -e /bin -e /cmd -e /examples)
|
||||
|
||||
test-e2e: test-e2e-postgres test-e2e-mysql test-e2e-clickhouse test-e2e-vertica test-e2e-ydb test-e2e-turso test-e2e-duckdb
|
||||
test-e2e: test-e2e-postgres test-e2e-mysql test-e2e-clickhouse test-e2e-vertica test-e2e-ydb test-e2e-turso
|
||||
|
||||
test-e2e-postgres:
|
||||
go test $(GO_TEST_FLAGS) ./tests/e2e -dialect=postgres
|
||||
|
@ -62,9 +62,6 @@ test-e2e-ydb:
|
|||
test-e2e-turso:
|
||||
go test $(GO_TEST_FLAGS) -parallel=1 ./tests/e2e -dialect=turso
|
||||
|
||||
test-e2e-duckdb:
|
||||
go test $(GO_TEST_FLAGS) -parallel=1 ./tests/e2e -dialect=duckdb
|
||||
|
||||
docker-cleanup:
|
||||
docker stop -t=0 $$(docker ps --filter="label=goose_test" -aq)
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ This will install the `goose` binary to your `$GOPATH/bin` directory.
|
|||
For a lite version of the binary without DB connection dependent commands, use the exclusive build tags:
|
||||
|
||||
```shell
|
||||
go build -tags='no_postgres no_mysql no_sqlite3 no_ydb no_duckdb' -o goose ./cmd/goose
|
||||
go build -tags='no_postgres no_mysql no_sqlite3 no_ydb' -o goose ./cmd/goose
|
||||
```
|
||||
|
||||
For macOS users `goose` is available as a [Homebrew Formulae](https://formulae.brew.sh/formula/goose#default):
|
||||
|
@ -81,7 +81,6 @@ Drivers:
|
|||
clickhouse
|
||||
vertica
|
||||
ydb
|
||||
duckdb
|
||||
|
||||
Examples:
|
||||
goose sqlite3 ./foo.db status
|
||||
|
@ -98,7 +97,6 @@ Examples:
|
|||
goose clickhouse "tcp://127.0.0.1:9000" status
|
||||
goose vertica "vertica://user:password@localhost:5433/dbname?connection_load_balance=1" status
|
||||
goose ydb "grpcs://localhost:2135/local?go_query_mode=scripting&go_fake_tx=scripting&go_query_bind=declare,numeric" status
|
||||
goose duckdb ./foo.db status
|
||||
|
||||
GOOSE_DRIVER=sqlite3 GOOSE_DBSTRING=./foo.db goose status
|
||||
GOOSE_DRIVER=sqlite3 GOOSE_DBSTRING=./foo.db goose create init sql
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
//go:build !no_duckdb && !windows && !linux && !darwin
|
||||
// +build !no_duckdb,!windows,!linux,!darwin
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/marcboeker/go-duckdb"
|
||||
)
|
|
@ -253,7 +253,6 @@ Drivers:
|
|||
vertica
|
||||
ydb
|
||||
turso
|
||||
duckdb
|
||||
|
||||
Examples:
|
||||
goose sqlite3 ./foo.db status
|
||||
|
@ -270,8 +269,7 @@ Examples:
|
|||
goose clickhouse "tcp://127.0.0.1:9000" status
|
||||
goose vertica "vertica://user:password@localhost:5433/dbname?connection_load_balance=1" status
|
||||
goose ydb "grpcs://localhost:2135/local?go_query_mode=scripting&go_fake_tx=scripting&go_query_bind=declare,numeric" status
|
||||
goose turso "libsql://dbname.turso.io?authToken=token" status
|
||||
goose duckdb ./foo.db status
|
||||
goose turso "libsql://dbname.turso.io?authToken=token" status
|
||||
|
||||
GOOSE_DRIVER=sqlite3 GOOSE_DBSTRING=./foo.db goose status
|
||||
GOOSE_DRIVER=sqlite3 GOOSE_DBSTRING=./foo.db goose create init sql
|
||||
|
@ -279,7 +277,6 @@ Examples:
|
|||
GOOSE_DRIVER=mysql GOOSE_DBSTRING="user:password@/dbname" goose status
|
||||
GOOSE_DRIVER=redshift GOOSE_DBSTRING="postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db" goose status
|
||||
GOOSE_DRIVER=turso GOOSE_DBSTRING="libsql://dbname.turso.io?authToken=token" goose status
|
||||
GOOSE_DRIVER=duckdb GOOSE_DBSTRING=./foo.db goose status
|
||||
|
||||
Options:
|
||||
`
|
||||
|
|
|
@ -23,7 +23,6 @@ const (
|
|||
DialectVertica Dialect = "vertica"
|
||||
DialectYdB Dialect = "ydb"
|
||||
DialectTurso Dialect = "turso"
|
||||
DialectDuckDB Dialect = "duckdb"
|
||||
)
|
||||
|
||||
// NewStore returns a new [Store] implementation for the given dialect.
|
||||
|
@ -45,7 +44,6 @@ func NewStore(dialect Dialect, tablename string) (Store, error) {
|
|||
DialectVertica: &dialectquery.Vertica{},
|
||||
DialectYdB: &dialectquery.Ydb{},
|
||||
DialectTurso: &dialectquery.Turso{},
|
||||
DialectDuckDB: &dialectquery.Duckdb{},
|
||||
}
|
||||
querier, ok := lookup[dialect]
|
||||
if !ok {
|
||||
|
|
2
db.go
2
db.go
|
@ -36,7 +36,7 @@ func OpenDBWithDriver(driver string, dbstring string) (*sql.DB, error) {
|
|||
}
|
||||
|
||||
switch driver {
|
||||
case "postgres", "pgx", "sqlite3", "sqlite", "mysql", "sqlserver", "clickhouse", "vertica", "azuresql", "ydb", "libsql", "duckdb":
|
||||
case "postgres", "pgx", "sqlite3", "sqlite", "mysql", "sqlserver", "clickhouse", "vertica", "azuresql", "ydb", "libsql":
|
||||
return sql.Open(driver, dbstring)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported driver %s", driver)
|
||||
|
|
|
@ -20,7 +20,6 @@ const (
|
|||
DialectTiDB Dialect = database.DialectTiDB
|
||||
DialectVertica Dialect = database.DialectVertica
|
||||
DialectYdB Dialect = database.DialectYdB
|
||||
DialectDuckDB Dialect = database.DialectDuckDB
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -53,8 +52,6 @@ func SetDialect(s string) error {
|
|||
d = dialect.Ydb
|
||||
case "turso":
|
||||
d = dialect.Turso
|
||||
case "duckdb":
|
||||
d = dialect.Duckdb
|
||||
default:
|
||||
return fmt.Errorf("%q: unknown dialect", s)
|
||||
}
|
||||
|
|
1
go.mod
1
go.mod
|
@ -6,7 +6,6 @@ require (
|
|||
github.com/ClickHouse/clickhouse-go/v2 v2.17.1
|
||||
github.com/go-sql-driver/mysql v1.7.1
|
||||
github.com/jackc/pgx/v5 v5.5.2
|
||||
github.com/marcboeker/go-duckdb v1.5.6
|
||||
github.com/mfridman/interpolate v0.0.2
|
||||
github.com/microsoft/go-mssqldb v1.6.0
|
||||
github.com/ory/dockertest/v3 v3.10.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -169,8 +169,6 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx
|
|||
github.com/lib/pq v0.0.0-20180327071824-d34b9ff171c2 h1:hRGSmZu7j271trc9sneMrpOW7GN5ngLm8YUZIPzf394=
|
||||
github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475 h1:6PfEMwfInASh9hkN83aR0j4W/eKaAZt/AURtXAXlas0=
|
||||
github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475/go.mod h1:20nXSmcf0nAscrzqsXeC2/tA3KkV2eCiJqYuyAgl+ss=
|
||||
github.com/marcboeker/go-duckdb v1.5.6 h1:5+hLUXRuKlqARcnW4jSsyhCwBRlu4FGjM0UTf2Yq5fw=
|
||||
github.com/marcboeker/go-duckdb v1.5.6/go.mod h1:wm91jO2GNKa6iO9NTcjXIRsW+/ykPoJbQcHSXhdAl28=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
|
|
|
@ -185,7 +185,7 @@ func buildGooseCLI(t *testing.T, lite bool) gooseBinary {
|
|||
"-ldflags=-s -w -X main.version=" + gooseTestBinaryVersion,
|
||||
}
|
||||
if lite {
|
||||
args = append(args, "-tags=no_clickhouse no_mssql no_mysql no_vertica no_postgres no_duckdb")
|
||||
args = append(args, "-tags=no_clickhouse no_mssql no_mysql no_vertica no_postgres")
|
||||
}
|
||||
args = append(args, "./cmd/goose")
|
||||
build := exec.Command("go", args...)
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
package dialectquery
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Duckdb struct{}
|
||||
|
||||
var _ Querier = (*Duckdb)(nil)
|
||||
|
||||
func (s *Duckdb) CreateTable(tableName string) string {
|
||||
q := `
|
||||
CREATE SEQUENCE %s_id;
|
||||
CREATE TABLE %s (
|
||||
id BIGINT PRIMARY KEY DEFAULT NEXTVAL('%s_id'),
|
||||
version_id BIGINT NOT NULL,
|
||||
is_applied BOOLEAN NOT NULL,
|
||||
tstamp TIMESTAMP DEFAULT (current_date())
|
||||
)`
|
||||
return fmt.Sprintf(q, tableName, tableName, tableName)
|
||||
}
|
||||
|
||||
func (s *Duckdb) InsertVersion(tableName string) string {
|
||||
q := `INSERT INTO %s (version_id, is_applied) VALUES (?, ?)`
|
||||
return fmt.Sprintf(q, tableName)
|
||||
}
|
||||
|
||||
func (s *Duckdb) DeleteVersion(tableName string) string {
|
||||
q := `DELETE FROM %s WHERE version_id=?`
|
||||
return fmt.Sprintf(q, tableName)
|
||||
}
|
||||
|
||||
func (s *Duckdb) GetMigrationByVersion(tableName string) string {
|
||||
q := `SELECT tstamp, is_applied FROM %s WHERE version_id=? ORDER BY tstamp DESC LIMIT 1`
|
||||
return fmt.Sprintf(q, tableName)
|
||||
}
|
||||
|
||||
func (s *Duckdb) ListMigrations(tableName string) string {
|
||||
q := `SELECT version_id, is_applied from %s ORDER BY id DESC`
|
||||
return fmt.Sprintf(q, tableName)
|
||||
}
|
|
@ -14,5 +14,4 @@ const (
|
|||
Vertica Dialect = "vertica"
|
||||
Ydb Dialect = "ydb"
|
||||
Turso Dialect = "turso"
|
||||
Duckdb Dialect = "duckdb"
|
||||
)
|
||||
|
|
|
@ -69,8 +69,6 @@ func NewStore(d Dialect) (Store, error) {
|
|||
querier = &dialectquery.Ydb{}
|
||||
case Turso:
|
||||
querier = &dialectquery.Turso{}
|
||||
case Duckdb:
|
||||
querier = &dialectquery.Duckdb{}
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown querier dialect: %v", d)
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package testdb
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"os"
|
||||
|
||||
_ "github.com/marcboeker/go-duckdb"
|
||||
)
|
||||
|
||||
func newDuckDB(opts ...OptionsFunc) (*sql.DB, func(), error) {
|
||||
option := &options{}
|
||||
for _, f := range opts {
|
||||
f(option)
|
||||
}
|
||||
|
||||
db, err := sql.Open("duckdb", option.databaseFile)
|
||||
|
||||
cleanup := func() {
|
||||
_ = db.Close()
|
||||
|
||||
_ = os.Remove(option.databaseFile)
|
||||
}
|
||||
|
||||
return db, cleanup, err
|
||||
}
|
|
@ -3,8 +3,6 @@ package testdb
|
|||
type options struct {
|
||||
bindPort int
|
||||
debug bool
|
||||
// for embedded databases
|
||||
databaseFile string
|
||||
}
|
||||
|
||||
type OptionsFunc func(o *options)
|
||||
|
@ -16,7 +14,3 @@ func WithBindPort(n int) OptionsFunc {
|
|||
func WithDebug(b bool) OptionsFunc {
|
||||
return func(o *options) { o.debug = b }
|
||||
}
|
||||
|
||||
func WithDatabaseFile(p string) OptionsFunc {
|
||||
return func(o *options) { o.databaseFile = p }
|
||||
}
|
||||
|
|
|
@ -26,8 +26,3 @@ func NewVertica(options ...OptionsFunc) (db *sql.DB, cleanup func(), err error)
|
|||
func NewYdb(options ...OptionsFunc) (db *sql.DB, cleanup func(), err error) {
|
||||
return newYdb(options...)
|
||||
}
|
||||
|
||||
// NewDuckDB opens a DuckDB database file. Returns a db connection and a cleanup function.
|
||||
func NewDuckDB(options ...OptionsFunc) (db *sql.DB, cleanup func(), err error) {
|
||||
return newDuckDB(options...)
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ const (
|
|||
dialectMySQL = "mysql"
|
||||
dialectYdb = "ydb"
|
||||
dialectTurso = "turso"
|
||||
dialectDuckDB = "duckdb"
|
||||
)
|
||||
|
||||
// Flags.
|
||||
|
@ -69,7 +68,7 @@ func TestMain(m *testing.M) {
|
|||
flag.Parse()
|
||||
|
||||
switch *dialect {
|
||||
case dialectPostgres, dialectMySQL, dialectYdb, dialectTurso, dialectDuckDB:
|
||||
case dialectPostgres, dialectMySQL, dialectYdb, dialectTurso:
|
||||
default:
|
||||
log.Printf("dialect not supported: %q", *dialect)
|
||||
os.Exit(1)
|
||||
|
@ -118,9 +117,6 @@ func newDockerDB(t *testing.T) (*sql.DB, error) {
|
|||
db, cleanup, err = testdb.NewYdb(options...)
|
||||
case dialectTurso:
|
||||
db, cleanup, err = testdb.NewTurso(options...)
|
||||
case dialectDuckDB:
|
||||
options = append(options, testdb.WithDatabaseFile(filepath.Join(t.TempDir(), "duck.db")))
|
||||
db, cleanup, err = testdb.NewDuckDB(options...)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported dialect: %q", *dialect)
|
||||
}
|
||||
|
|
|
@ -367,10 +367,6 @@ func getTableNames(db *sql.DB) (tableNames []string, _ error) {
|
|||
return tableNames, nil
|
||||
case dialectTurso:
|
||||
return getTableNamesThroughQuery(db, `SELECT NAME FROM sqlite_master where type='table' and name!='sqlite_sequence' ORDER BY NAME;`)
|
||||
case dialectDuckDB:
|
||||
return getTableNamesThroughQuery(db,
|
||||
`SELECT table_name FROM information_schema.tables ORDER BY table_name`,
|
||||
)
|
||||
default:
|
||||
return nil, fmt.Errorf("getTableNames not supported with dialect %q", *dialect)
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE SEQUENCE owner_id;
|
||||
CREATE TABLE owners (
|
||||
owner_id INTEGER PRIMARY KEY DEFAULT NEXTVAL('owner_id'),
|
||||
owner_name VARCHAR,
|
||||
owner_type VARCHAR
|
||||
);
|
||||
CREATE SEQUENCE repo_id;
|
||||
CREATE TABLE repos (
|
||||
repo_id INTEGER PRIMARY KEY DEFAULT NEXTVAL('repo_id'),
|
||||
repo_owner_id INTEGER,
|
||||
repo_full_name VARCHAR
|
||||
);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE repos;
|
||||
DROP SEQUENCE repo_id;
|
||||
DROP TABLE owners;
|
||||
DROP SEQUENCE owner_id;
|
||||
-- +goose StatementEnd
|
|
@ -1,10 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
INSERT INTO owners(owner_id, owner_name, owner_type)
|
||||
VALUES (1, 'lucas', 'user'), (2, 'space', 'organization');
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DELETE FROM owners;
|
||||
-- +goose StatementEnd
|
|
@ -1,13 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
INSERT INTO owners(owner_id, owner_name, owner_type)
|
||||
VALUES (3, 'james', 'user'), (4, 'pressly', 'organization');
|
||||
INSERT INTO repos(repo_id, repo_full_name, repo_owner_id)
|
||||
VALUES (1, 'james/rover', 3), (2, 'pressly/goose', 4);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DELETE FROM owners WHERE (owner_id = 3 OR owner_id = 4);
|
||||
DELETE FROM repos WHERE (repo_id = 1 OR repo_id = 2);
|
||||
-- +goose StatementEnd
|
|
@ -1,15 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
ALTER TABLE repos
|
||||
ADD COLUMN homepage_url text;
|
||||
ALTER TABLE repos
|
||||
ADD COLUMN is_private integer;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
ALTER TABLE repos
|
||||
DROP COLUMN homepage_url;
|
||||
ALTER TABLE repos
|
||||
DROP COLUMN is_private;
|
||||
-- +goose StatementEnd
|
|
@ -1,11 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
-- NOTE: intentionally left blank to verify migration logic.
|
||||
SELECT 'up SQL query';
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
-- NOTE: intentionally left blank to verify migration logic.
|
||||
SELECT 'down SQL query';
|
||||
-- +goose StatementEnd
|
|
@ -1,15 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE stargazers (
|
||||
stargazer_repo_id integer,
|
||||
stargazer_owner_id integer,
|
||||
stargazer_starred_at integer,
|
||||
stargazer_location text,
|
||||
PRIMARY KEY (stargazer_repo_id, stargazer_owner_id)
|
||||
);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE stargazers;
|
||||
-- +goose StatementEnd
|
|
@ -1,16 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE issues (
|
||||
issue_id integer,
|
||||
issue_created_by integer,
|
||||
issue_repo_id integer,
|
||||
issue_created_at integer,
|
||||
issue_description text,
|
||||
PRIMARY KEY (issue_id)
|
||||
);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE issues;
|
||||
-- +goose StatementEnd
|
|
@ -1,9 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
ALTER TABLE stargazers DROP COLUMN stargazer_location;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
ALTER TABLE stargazers ADD COLUMN stargazer_location text;
|
||||
-- +goose StatementEnd
|
Loading…
Reference in New Issue