Skip to content

Commit

Permalink
Be way less aggressive with removing CREATE DATABASE or USE statement…
Browse files Browse the repository at this point in the history
…s in ddev import-db, fixes ddev#2787 (ddev#2831)

* Be way less aggressive with removing CREATE DATABASE or USE statuements in ddev import-db, fixes ddev#2787
* Add section to TestDdevImportDB to check for database content corruption
* Test both with file input and stdin input
  • Loading branch information
rfay authored Feb 26, 2021
1 parent 21a98d8 commit 8cf313e
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 3 deletions.
10 changes: 7 additions & 3 deletions pkg/ddevapp/ddevapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,12 +507,16 @@ func (app *DdevApp) ImportDB(imPath string, extPath string, progress bool, noDro
}

// The perl manipulation removes statements like CREATE DATABASE and USE, which
// throw off imports.
inContainerCommand := fmt.Sprintf(`mysql -uroot -proot -e "%s" && pv %s/*.*sql | perl -p -e 's/^(CREATE DATABASE|USE|.*DROP DATABASE).*$//' | mysql %s`, preImportSQL, insideContainerImportPath, targetDB)
// throw off imports. This is a scary manipulation, as it must not match actual content
// as has actually happened with https://www.ddev.com/ddev-local/ddev-local-database-management/
// and in https://github.com/drud/ddev/issues/2787
// The backtick after USE is inserted via fmt.Sprintf argument because it seems there's
// no way to escape a backtick in a string literal.
inContainerCommand := fmt.Sprintf(`mysql -uroot -proot -e "%s" && pv %s/*.*sql | perl -p -e 's/^(CREATE DATABASE \/\*|USE %s)[^;]*;//' | mysql %s`, preImportSQL, insideContainerImportPath, "`", targetDB)

// Handle the case where we are reading from stdin
if imPath == "" && extPath == "" {
inContainerCommand = fmt.Sprintf(`mysql -uroot -proot -e "%s" && perl -p -e 's/^(CREATE DATABASE|USE|.*DROP DATABASE).*$//' | mysql %s`, preImportSQL, targetDB)
inContainerCommand = fmt.Sprintf(`mysql -uroot -proot -e "%s" && perl -p -e 's/^(CREATE DATABASE \/\*|USE %s)[^;]*;//' | mysql %s`, preImportSQL, "`", targetDB)
}
_, _, err = app.Exec(&ExecOpts{
Service: "db",
Expand Down
56 changes: 56 additions & 0 deletions pkg/ddevapp/ddevapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,41 @@ func TestDdevImportDB(t *testing.T) {
}
}

// Test database that has SQL DDL in the content to make sure nothing gets corrupted.
_, _, err = app.Exec(&ddevapp.ExecOpts{Service: "db", Cmd: "mysql -N -e 'DROP TABLE IF EXISTS wp_posts;'"})
require.NoError(t, err)
file := "posts_with_ddl_content.sql"
path := filepath.Join(testDir, "testdata", t.Name(), file)
err = app.ImportDB(path, "", false, false, "db")
assert.NoError(err, "Failed to app.ImportDB path: %s err: %v", path, err)
checkImportDbImports(t, app)

// Now test the same when importing from stdin, same file
_, _, err = app.Exec(&ddevapp.ExecOpts{Service: "db", Cmd: "mysql -N -e 'DROP TABLE wp_posts;'"})
require.NoError(t, err)
f, err := os.Open(path)
require.NoError(t, err)
defer f.Close()
oldStdin := os.Stdin
t.Cleanup(func() {
os.Stdin = oldStdin
})
os.Stdin = f
err = app.ImportDB("", "", false, false, "db")
assert.NoError(err, "Failed to app.ImportDB path: %s err: %v", path, err)
os.Stdin = oldStdin
checkImportDbImports(t, app)

// Verify that the count of tables is exactly what it should be, that nothing was lost in the
// import due to embedded DDL statements.
out, _, err := app.Exec(&ddevapp.ExecOpts{
Service: "db",
Cmd: `mysql -N -e 'SELECT COUNT(*) FROM wp_posts;'`,
})
assert.NoError(err)
assert.Equal("180\n", out)

// Now check standard archive imports
if site.DBTarURL != "" {
_, cachedArchive, err := testcommon.GetCachedArchive(site.Name, site.Name+"_siteTarArchive", "", site.DBTarURL)
require.NoError(t, err)
Expand Down Expand Up @@ -1042,6 +1077,27 @@ func TestDdevImportDB(t *testing.T) {
switchDir()
}

func checkImportDbImports(t *testing.T, app *ddevapp.DdevApp) {
assert := asrt.New(t)

// There should be exactly the one wp_posts table for this file
out, _, err := app.Exec(&ddevapp.ExecOpts{
Service: "db",
Cmd: "mysql -N -e 'SHOW TABLES;' | cat",
})
assert.NoError(err)
assert.Equal("wp_posts\n", out)

// Verify that no extra database was created (this one has a CREATE DATABASE statement)
out, _, err = app.Exec(&ddevapp.ExecOpts{
Service: "db",
Cmd: `mysql -N -e 'SHOW DATABASES;' | egrep -v "^(information_schema|performance_schema|mysql)$"`,
})
assert.NoError(err)
assert.Equal("db\n", out)

}

// TestDdevAllDatabases tests db import/export/start with all MariaDB versions
func TestDdevAllDatabases(t *testing.T) {
assert := asrt.New(t)
Expand Down
85 changes: 85 additions & 0 deletions pkg/ddevapp/testdata/TestDdevImportDB/posts_with_ddl_content.sql

Large diffs are not rendered by default.

0 comments on commit 8cf313e

Please sign in to comment.