Skip to content

Commit

Permalink
feat: dbmate dump duckdb driver support
Browse files Browse the repository at this point in the history
  • Loading branch information
PadenZach committed Sep 20, 2024
1 parent 3c8a90a commit d0890ef
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 10 deletions.
42 changes: 38 additions & 4 deletions pkg/driver/duckdb/duckdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,24 +133,58 @@ func (drv *Driver) schemaMigrationsDump(db *sql.DB) ([]byte, error) {
}

// DumpSchema returns the current database schema
// TODO: Need to change this to use a different command.
// Will probably need to call export database or something.
func (drv *Driver) DumpSchema(db *sql.DB) ([]byte, error) {
path := ConnectionString(drv.databaseURL)
schema, err := dbutil.RunCommand("sqlite3", path, ".schema --nosys")
query_string := `SELECT sql FROM (
SELECT COALESCE(sql, format('CREATE SCHEMA {}', schema_name)) AS sql from duckdb_schemas() where internal=false
UNION ALL
SELECT sql from duckdb_sequences()
UNION ALL
SELECT sql from duckdb_tables() where internal=false
UNION ALL
SELECT sql from duckdb_indexes()
UNION ALL
SELECT sql from duckdb_views() WHERE internal=false AND sql is not null
UNION ALL
SELECT macro_definition from duckdb_functions() WHERE internal=false and macro_definition is not null
) WHERE sql IS NOT NULL;
`
rows, err := db.Query(query_string)
if err != nil {
return nil, err
}
defer rows.Close()

var schema []byte

// Iterate over the rows and build the schema
for rows.Next() {
var sqlStmt string
if err := rows.Scan(&sqlStmt); err != nil {
return nil, err
}
// Append each SQL statement to the schema slice
schema = append(schema, []byte(sqlStmt+"\n")...)
}

// Check for any errors encountered during iteration
if err := rows.Err(); err != nil {
return nil, err
}

// Add any migrations to the schema
migrations, err := drv.schemaMigrationsDump(db)
if err != nil {
return nil, err
}

// Append the migrations to the schema
schema = append(schema, migrations...)

// Trim leading comments or unnecessary lines from the schema
return dbutil.TrimLeadingSQLComments(schema)
}


// DatabaseExists determines whether the database exists
func (drv *Driver) DatabaseExists() (bool, error) {
_, err := os.Stat(ConnectionString(drv.databaseURL))
Expand Down
11 changes: 5 additions & 6 deletions pkg/driver/duckdb/duckdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"testing"
"strings"
"fmt"

Check failure on line 11 in pkg/driver/duckdb/duckdb_test.go

View workflow job for this annotation

GitHub Actions / Build (linux/amd64)

"fmt" imported and not used

Check failure on line 11 in pkg/driver/duckdb/duckdb_test.go

View workflow job for this annotation

GitHub Actions / Build (macos/amd64)

"fmt" imported and not used

"github.com/amacneil/dbmate/v2/pkg/dbmate"
"github.com/amacneil/dbmate/v2/pkg/dbtest"
Expand Down Expand Up @@ -192,23 +193,21 @@ func TestDuckDBDumpSchema(t *testing.T) {
err = drv.InsertMigration(db, "abc2")
require.NoError(t, err)

// create a table that will trigger `duckdb_sequence` system table
_, err = db.Exec("CREATE TABLE t (id INTEGER PRIMARY KEY AUTOINCREMENT)")
// create a table
_, err = db.Exec("CREATE TABLE t (id INTEGER PRIMARY KEY)")
require.NoError(t, err)

// DumpSchema should return schema
schema, err := drv.DumpSchema(db)
require.NoError(t, err)
require.Contains(t, string(schema), "CREATE TABLE t (id INTEGER PRIMARY KEY AUTOINCREMENT)")

require.Contains(t, string(schema), "CREATE TABLE t (id INTEGER PRIMARY KEY)")
require.Contains(t, string(schema), "CREATE TABLE IF NOT EXISTS \"test_migrations\"")
require.Contains(t, string(schema), ");\n-- Dbmate schema migrations\n"+
"INSERT INTO \"test_migrations\" (version) VALUES\n"+
" ('abc1'),\n"+
" ('abc2');\n")

// duckdb_* tables should not be present in the dump (.schema --nosys)
require.NotContains(t, string(schema), "duckdb_")

// DumpSchema should return error if command fails
drv.databaseURL = dbtest.MustParseURL(t, ".")
schema, err = drv.DumpSchema(db)
Expand Down

0 comments on commit d0890ef

Please sign in to comment.