Skip to content

Commit 05faef8

Browse files
committed
amend dolt_backup impl to work in non-dolt directories
1 parent 6fc0e63 commit 05faef8

File tree

5 files changed

+110
-54
lines changed

5 files changed

+110
-54
lines changed

go/cmd/dolt/commands/backup.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import (
2929
eventsapi "github.com/dolthub/eventsapi_schema/dolt/services/eventsapi/v1alpha1"
3030
)
3131

32+
const DoltBackupCommandName = "backup"
33+
3234
var backupDocs = cli.CommandDocumentationContent{
3335
ShortDesc: "Manage database backups, including creation, sync, and restore.",
3436
LongDesc: `

go/cmd/dolt/dolt.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -680,8 +680,14 @@ If you're interested in running this command against a remote host, hit us up on
680680
//
681681
// This is also allowed when --help is passed. So we defer the error
682682
// until the caller tries to use the cli.LateBindQueryist.
683-
isValidRepositoryRequired := subcommandName != "init" && subcommandName != "sql" && subcommandName != "sql-server" && subcommandName != "sql-client"
684-
683+
commandsNotRequiringRepo := map[string]bool{
684+
"init": true,
685+
"sql": true,
686+
"sql-server": true,
687+
"sql-client": true,
688+
commands.DoltBackupCommandName: true,
689+
}
690+
isValidRepositoryRequired := !commandsNotRequiringRepo[subcommandName]
685691
if noValidRepository && isValidRepositoryRequired {
686692
return func(ctx context.Context, opts ...cli.LateBindQueryistOption) (res cli.LateBindQueryistResult, err error) {
687693
err = errors.New("The current directory is not a valid dolt repository.")

go/libraries/doltcore/sqle/dprocedures/dolt_backup.go

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/dolthub/dolt/go/libraries/doltcore/sqlserver"
3232
"github.com/dolthub/dolt/go/libraries/utils/argparser"
3333
"github.com/dolthub/dolt/go/store/datas/pull"
34+
"github.com/dolthub/dolt/go/store/types"
3435
)
3536

3637
const (
@@ -55,17 +56,25 @@ var awsParamsUsage = []string{
5556
// based on the first argument. The procedure requires superuser privileges and write access to the current database.
5657
// Supported operations are: add, remove/rm, sync, sync-url, and restore.
5758
func doltBackup(ctx *sql.Context, args ...string) (sql.RowIter, error) {
58-
dbName := ctx.GetCurrentDatabase()
59-
if dbName == "" {
60-
return nil, fmt.Errorf("empty database name")
61-
}
62-
63-
err := branch_control.CheckAccess(ctx, branch_control.Permissions_Write)
59+
apr, err := cli.CreateBackupArgParser().Parse(args)
6460
if err != nil {
6561
return nil, err
6662
}
6763

68-
apr, err := cli.CreateBackupArgParser().Parse(args)
64+
if apr.NArg() == 0 || (apr.NArg() == 1 && apr.Contains(cli.VerboseFlag)) {
65+
return nil, fmt.Errorf("use '%s' table to list backups", doltdb.BackupsTableName)
66+
}
67+
68+
var dbName string
69+
funcParam := apr.Arg(0)
70+
if funcParam != DoltBackupParamRestore {
71+
dbName = ctx.GetCurrentDatabase()
72+
if dbName == "" {
73+
return nil, fmt.Errorf("empty database name")
74+
}
75+
}
76+
77+
err = branch_control.CheckAccess(ctx, branch_control.Permissions_Write)
6978
if err != nil {
7079
return nil, err
7180
}
@@ -82,17 +91,12 @@ func doltBackup(ctx *sql.Context, args ...string) (sql.RowIter, error) {
8291
}
8392
}
8493

85-
if apr.NArg() == 0 || (apr.NArg() == 1 && apr.Contains(cli.VerboseFlag)) {
86-
return nil, fmt.Errorf("use '%s' table to list backups", doltdb.BackupsTableName)
87-
}
88-
8994
doltSess := dsess.DSessFromSess(ctx.Session)
9095
dbData, ok := doltSess.GetDbData(ctx, dbName)
91-
if !ok {
96+
if !ok && funcParam != DoltBackupParamRestore {
9297
return nil, sql.ErrDatabaseNotFound.New(dbName)
9398
}
9499

95-
funcParam := apr.Arg(0)
96100
switch funcParam {
97101
case DoltBackupParamAdd:
98102
if apr.NArg() != 3 {
@@ -225,7 +229,14 @@ func doltBackupRestore(ctx *sql.Context, dbData env.DbData[*sql.Context], dsess
225229
}
226230

227231
remote := env.NewRemote(DoltBackupParamRestore, remoteUrl, remoteParams)
228-
remoteDb, err := dsess.Provider().GetRemoteDB(ctx, dbData.Ddb.Format(), remote, true)
232+
233+
// Use default format if no database context is available (e.g., when run from invalid directory).
234+
format := types.Format_Default
235+
if dbData.Ddb != nil {
236+
format = dbData.Ddb.Format()
237+
}
238+
239+
remoteDb, err := dsess.Provider().GetRemoteDB(ctx, format, remote, true)
229240
if err != nil {
230241
return err
231242
}
@@ -247,7 +258,7 @@ func doltBackupRestore(ctx *sql.Context, dbData env.DbData[*sql.Context], dsess
247258
}
248259
}
249260

250-
if lookupDbInFileSys {
261+
if lookupDbInFileSys && !hasLookupDb {
251262
err = fileSys.Delete(lookupDbName, forceRestore)
252263
if err != nil {
253264
return err

integration-tests/bats/helper/local-remote.bash

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ SKIP_SERVER_TESTS=$(cat <<-EOM
6868
~arg-parsing.bats~
6969
~dump.bats~
7070
~rename-tables.bats~
71-
~sql-backup.bats~
7271
~drop-create.bats~
7372
~constraint-violations.bats~
7473
~branch-control.bats~

integration-tests/bats/sql-backup.bats

Lines changed: 74 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@ setup() {
77
}
88

99
teardown() {
10-
stop_sql_server
1110
teardown_common
1211
}
1312

1413
@test "sql-backup: dolt_backup no argument" {
1514
run dolt sql -q "call dolt_backup()"
1615
[ "$status" -ne 0 ]
16+
[[ "$output" =~ "use 'dolt_backups' table to list backups" ]]
1717
run dolt sql -q "CALL dolt_backup()"
1818
[ "$status" -ne 0 ]
19+
[[ "$output" =~ "use 'dolt_backups' table to list backups" ]]
1920
}
2021

2122
@test "sql-backup: dolt_backup add" {
@@ -28,16 +29,16 @@ teardown() {
2829
}
2930

3031
@test "sql-backup: dolt_backup add cannot add remote with address of existing backup" {
31-
mkdir bac1
32-
dolt sql -q "call dolt_backup('add','bac1','file://./bac1')"
33-
run dolt sql -q "call dolt_backup('add','rem1','file://./bac1')"
32+
backupFileUrl="file://$BATS_TEST_TMPDIR/backup"
33+
dolt sql -q "call dolt_backup('add','bac1', '$backupFileUrl')"
34+
run dolt sql -q "call dolt_backup('add','rem1', '$backupFileUrl')"
3435
[ "$status" -eq 1 ]
3536
[[ "$output" =~ "address conflict with a remote: 'bac1'" ]] || false
3637
}
3738

3839
@test "sql-backup: dolt_backup remove" {
39-
mkdir bac1
40-
dolt sql -q "call dolt_backup('add', 'bac1', 'file://./bac1')"
40+
backupFileUrl="file://$BATS_TEST_TMPDIR/backup"
41+
dolt sql -q "call dolt_backup('add', 'bac1', '$backupFileUrl')"
4142
run dolt backup -v
4243
[ "$status" -eq 0 ]
4344
[ "${#lines[@]}" -eq 1 ]
@@ -61,8 +62,8 @@ teardown() {
6162
}
6263

6364
@test "sql-backup: dolt_backup rm" {
64-
mkdir bac1
65-
dolt sql -q "call dolt_backup('add', 'bac1', 'file://./bac1')"
65+
backupFileUrl="files://$BATS_TEST_TMPDIR/backup"
66+
dolt sql -q "call dolt_backup('add', 'bac1', '$backupFileUrl')"
6667
run dolt backup -v
6768
[ "$status" -eq 0 ]
6869
[ "${#lines[@]}" -eq 1 ]
@@ -93,18 +94,18 @@ teardown() {
9394
}
9495

9596
@test "sql-backup: dolt_backup restore" {
96-
backupsDir="$PWD/backups"
97+
backupFileUrl="file://$BATS_TEST_TMPDIR/backups"
9798
mkdir backupsDir
9899

99100
# Created a nested database, back it up, drop it, then restore it with a new name
100101
dolt sql -q "create database db1;"
101102
cd db1
102103
dolt sql -q "create table t1 (pk int primary key); insert into t1 values (42); call dolt_commit('-Am', 'creating table t1');"
103-
dolt sql -q "call dolt_backup('add', 'backups', 'file://$backupsDir');"
104+
dolt sql -q "call dolt_backup('add', 'backups', '$backupFileUrl');"
104105
dolt sql -q "call dolt_backup('sync', 'backups');"
105106
cd ..
106107
dolt sql -q "drop database db1;"
107-
dolt sql -q "call dolt_backup('restore', 'file://$backupsDir', 'db2');"
108+
dolt sql -q "call dolt_backup('restore', '$backupFileUrl', 'db2');"
108109

109110
# Assert that db2 is present, and db1 is not
110111
run dolt sql -q "show databases;"
@@ -124,33 +125,52 @@ teardown() {
124125
[ "${#lines[@]}" -eq 0 ]
125126
}
126127

127-
@test "sql-backup: dolt_backup restore --force" {
128-
backupsDir="$PWD/backups"
129-
mkdir backupsDir
128+
@test "sql-backup: dolt_backup restore --force on current database" {
129+
backupFileUrl="file://$BATS_TEST_TMPDIR/backups"
130130

131131
# Created a nested database, and back it up
132132
dolt sql -q "create database db1;"
133-
cd db1
134-
dolt sql -q "create table t1 (pk int primary key); insert into t1 values (42); call dolt_commit('-Am', 'creating table t1');"
135-
dolt sql -q "call dolt_backup('add', 'backups', 'file://$backupsDir');"
136-
dolt sql -q "call dolt_backup('sync', 'backups');"
133+
# We could cd into db1 but Windows does not like us touching its CWD when we drop the database when restoring.
134+
dolt sql -q "use db1; create table t1 (pk int primary key); insert into t1 values (42); call dolt_commit('-Am', 'creating table t1');"
135+
dolt sql -q "use db1; call dolt_backup('add', 'backups', '$backupFileUrl');"
136+
dolt sql -q "use db1; call dolt_backup('sync', 'backups');"
137137

138138
# Make a new commit in db1, but don't push it to the backup
139-
dolt sql -q "update t1 set pk=100; call dolt_commit('-Am', 'updating table t1');"
139+
dolt sql -q "use db1; update t1 set pk=100; call dolt_commit('-Am', 'updating table t1');"
140140

141141
# Assert that without --force, we can't update an existing db from a backup
142-
run dolt sql -q "call dolt_backup('restore', 'file://$backupsDir', 'db1');"
142+
run dolt sql -q "use db1; call dolt_backup('restore', '$backupFileUrl', 'db1');"
143143
[ "$status" -eq 1 ]
144144
[[ "$output" =~ "database 'db1' already exists, use '--force' to overwrite" ]] || false
145145

146146
# Use --force to overwrite the existing database and sanity check the data
147-
run dolt sql -q "call dolt_backup('restore', '--force', 'file://$backupsDir', 'db1');"
147+
run dolt sql -q "use db1; call dolt_backup('restore', '--force', '$backupFileUrl', 'db1');"
148148
[ "$status" -eq 0 ]
149149
run dolt sql -q "use db1; select * from t1;"
150150
[ "$status" -eq 0 ]
151151
[[ "$output" =~ "42" ]] || false
152152
}
153153

154+
@test "sql-backup: dolt_backup restore --force on current database and as cwd" {
155+
skiponwindows "Windows storage system locks the terminal cwd when trying to drop database in restore procedure; this includes mounted storage in WSL"
156+
backupFileUrl="$BATS_TEST_TMPDIR/backup"
157+
dolt sql -q "create database db1;"
158+
cd db1
159+
dolt sql <<'EOF'
160+
create table t (i int);
161+
insert into t values (3), (4);
162+
dolt_backup('sync-url', '$fileBackupUrl');
163+
EOF
164+
165+
run dolt sql -q "call dolt_backup('restore', '', 'db1');"
166+
[ "$status" -eq 1 ]
167+
[[ "$output" =~ "database 'db1' already exists, use '--force' to overwrite" ]] || false
168+
169+
run dolt sql -q "call dolt_backup('restore', '$backupFileUrl', 'db1');"
170+
[ "$status" -eq 0 ]
171+
[[ "$output" =~ i.*3.*4 ]]
172+
}
173+
154174
@test "sql-backup: dolt_backup unrecognized" {
155175
run dolt sql -q "call dolt_backup('unregonized', 'hostedapidb-0', 'file:///some_directory')"
156176
[ "$status" -ne 0 ]
@@ -177,37 +197,31 @@ teardown() {
177197
}
178198

179199
@test "sql-backup: dolt_backup sync to a backup" {
180-
mkdir the_backup
181-
dolt backup add hostedapidb-0 file://./the_backup
200+
backupFileUrl="file://$BATS_TEST_TMPDIR/the_backup"
201+
dolt backup add hostedapidb-0 "$backupFileUrl"
182202
dolt backup -v
183203
dolt sql -q "call dolt_backup('sync', 'hostedapidb-0')"
184204
# Initial backup works.
185-
dolt backup restore file://./the_backup the_restore
205+
dolt backup restore "$backupFileUrl" the_restore
186206
(cd the_restore && dolt status)
187207
# Backup with nothing to push works.
188208
dolt sql -q "call dolt_backup('sync', 'hostedapidb-0')"
189209

190-
rm -rf the_backup the_restore
191-
192-
mkdir the_backup
193210
dolt sql -q "CALL dolt_backup('sync', 'hostedapidb-0')"
194-
dolt backup restore file://./the_backup the_restore
211+
dolt backup restore "$backupFileUrl" the_restore --force
195212
(cd the_restore && dolt status)
196213
dolt sql -q "CALL dolt_backup('sync', 'hostedapidb-0')"
197214
}
198215

199216
@test "sql-backup: dolt_backup sync-url" {
200-
mkdir the_backup
201-
dolt sql -q "call dolt_backup('sync-url', 'file://./the_backup')"
217+
backupFileUrl="file://$BATS_TEST_TMPDIR/the_backup"
218+
dolt sql -q "call dolt_backup('sync-url', '$backupFileUrl')"
202219
# Initial backup works.
203-
dolt backup restore file://./the_backup the_restore
220+
dolt backup restore "$backupFileUrl" the_restore
204221
(cd the_restore && dolt status)
205222

206-
rm -rf the_backup the_restore
207-
208-
mkdir the_backup
209-
dolt sql -q "CALL dolt_backup('sync-url', 'file://./the_backup')"
210-
dolt backup restore file://./the_backup the_restore
223+
dolt sql -q "CALL dolt_backup('sync-url', '$backupFileUrl')"
224+
dolt backup restore "$backupFileUrl" the_restore --force
211225
(cd the_restore && dolt status)
212226
}
213227

@@ -219,6 +233,7 @@ teardown() {
219233
}
220234

221235
@test "sql-backup: dolt_backup rejects AWS parameters fails in sql-server" {
236+
skip_if_remote
222237
start_sql_server
223238

224239
run dolt sql -q "call dolt_backup('add', 'backup1', 'aws://[table:bucket]/db', '--aws-region=us-east-1')"
@@ -236,4 +251,27 @@ teardown() {
236251
run dolt sql -q "call dolt_backup('add', 'backup4', 'aws://[table:bucket]/db', '--aws-creds-profile=profile')"
237252
[ "$status" -eq 1 ]
238253
[[ "$output" =~ "AWS parameters are unavailable when running in server mode" ]] || false
254+
255+
stop_sql_server 1
256+
}
257+
258+
@test "sql-backup: dolt_backup works in invalid dolt repository" {
259+
backupFileUrl="file://$BATS_TEST_TMPDIR/t_backup"
260+
run dolt sql -q "create table t (i int);"
261+
[ "$status" -eq 0 ]
262+
run dolt sql -q "insert into t values (4), (3);"
263+
[ "$status" -eq 0 ]
264+
run dolt sql -q "call dolt_backup('sync-url', '$backupFileUrl')"
265+
[ "$status" -eq 0 ]
266+
267+
invalidRepoDir="$BATS_TEST_TMPDIR/invalid_repo"
268+
mkdir -p "$invalidRepoDir"
269+
cd $invalidRepoDir
270+
dolt sql -q "call dolt_backup('restore', '$backupFileUrl', 't_db')"
271+
[ "$status" -eq 0 ]
272+
273+
cd t_db
274+
run dolt sql --result-format csv -q "select * from t"
275+
[ "$status" -eq 0 ]
276+
[[ "$output" =~ i.*3.*4 ]]
239277
}

0 commit comments

Comments
 (0)