Skip to content

Commit ba23dab

Browse files
authored
Merge pull request #9668 from dolthub/fulghum/ws-init
Initialize a branch's working set when referenced as a branch-revision database
2 parents ca0622f + 92222d9 commit ba23dab

File tree

2 files changed

+88
-14
lines changed

2 files changed

+88
-14
lines changed

go/libraries/doltcore/sqle/dsess/session.go

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,25 +1411,36 @@ func (d *DoltSession) addDB(ctx *sql.Context, db SqlDatabase) error {
14111411

14121412
if dbState.Err != nil {
14131413
sessionState.Err = dbState.Err
1414-
} else if dbState.WorkingSet != nil {
1415-
branchState.workingSet = dbState.WorkingSet
1416-
1417-
// TODO: this is pretty clunky, there is a silly dependency between InitialDbState and globalstate.StateProvider
1418-
// that's hard to express with the current types
1419-
stateProvider, ok := db.(globalstate.GlobalStateProvider)
1420-
if !ok {
1421-
return fmt.Errorf("database does not contain global state store")
1414+
} else {
1415+
// If the dbState doesn't have a working set yet, try to
1416+
// initialize one – this will only initialize a working set
1417+
// if the database is a branch revision database.
1418+
if dbState.WorkingSet == nil {
1419+
if err := initializeBranchWorkingSet(ctx, db, &dbState); err != nil {
1420+
return err
1421+
}
14221422
}
1423-
sessionState.globalState = stateProvider.GetGlobalState()
14241423

1425-
tracker, err := sessionState.globalState.AutoIncrementTracker(ctx)
1426-
if err != nil {
1427-
return err
1424+
if dbState.WorkingSet != nil {
1425+
branchState.workingSet = dbState.WorkingSet
1426+
1427+
// TODO: this is pretty clunky, there is a silly dependency between InitialDbState and globalstate.StateProvider
1428+
// that's hard to express with the current types
1429+
stateProvider, ok := db.(globalstate.GlobalStateProvider)
1430+
if !ok {
1431+
return fmt.Errorf("database does not contain global state store")
1432+
}
1433+
sessionState.globalState = stateProvider.GetGlobalState()
1434+
1435+
tracker, err := sessionState.globalState.AutoIncrementTracker(ctx)
1436+
if err != nil {
1437+
return err
1438+
}
1439+
branchState.writeSession = d.writeSessProv(nbf, branchState.WorkingSet(), tracker, editOpts)
14281440
}
1429-
branchState.writeSession = d.writeSessProv(nbf, branchState.WorkingSet(), tracker, editOpts)
14301441
}
14311442

1432-
// WorkingSet is nil in the case of a read only, detached head DB
1443+
// WorkingSet is nil in the case of a read-only, detached head DB
14331444
if dbState.HeadCommit != nil {
14341445
headRoot, err := dbState.HeadCommit.GetRootValue(ctx)
14351446
if err != nil {
@@ -1747,6 +1758,41 @@ func (d *DoltSession) GCSafepointController() *gcctx.GCSafepointController {
17471758
return d.gcSafepointController
17481759
}
17491760

1761+
// initializeBranchWorkingSet checks if |db| is a branch revision database, and if |dbState|
1762+
// does not have a working set yet, then a new, empty working set is created and set in |dbState|.
1763+
// If |db| is NOT a branch revision database, or |dbState| already has a working set, then this
1764+
// function will not do anything.
1765+
func initializeBranchWorkingSet(ctx *sql.Context, db SqlDatabase, dbState *InitialDbState) error {
1766+
revisionDb, isRevisionDb := db.(RevisionDatabase)
1767+
if !isRevisionDb || revisionDb.RevisionType() != RevisionTypeBranch || dbState.WorkingSet != nil {
1768+
return nil
1769+
}
1770+
1771+
branchRef := ref.NewBranchRef(revisionDb.Revision())
1772+
wsRef, err := ref.WorkingSetRefForHead(branchRef)
1773+
if err != nil {
1774+
return err
1775+
}
1776+
1777+
commit, err := dbState.DbData.Ddb.ResolveCommitRef(ctx, branchRef)
1778+
if err != nil {
1779+
return err
1780+
}
1781+
1782+
headRoot, err := commit.GetRootValue(ctx)
1783+
if err != nil {
1784+
return err
1785+
}
1786+
1787+
dbState.WorkingSet = doltdb.EmptyWorkingSet(wsRef).
1788+
WithWorkingRoot(headRoot).WithStagedRoot(headRoot)
1789+
1790+
ctx.GetLogger().Warnf("initializing empty working set for branch %s", revisionDb.Revision())
1791+
1792+
return dbState.DbData.Ddb.UpdateWorkingSet(ctx, wsRef, dbState.WorkingSet,
1793+
hash.Hash{}, doltdb.TodoWorkingSetMeta(), nil)
1794+
}
1795+
17501796
// validatePersistedSysVar checks whether a system variable exists and is dynamic
17511797
func validatePersistableSysVar(name string) (sql.SystemVariable, interface{}, error) {
17521798
sysVar, val, ok := sql.SystemVariables.GetGlobal(name)

integration-tests/bats/sql-server-remotesrv.bats

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,34 @@ call dolt_commit('-am', 'add one val');"
430430
[[ "$output" =~ "dave" ]] || false
431431
}
432432

433+
# Assert that when a new branch that has been pushed to a running SQL server through the RemotesAPI,
434+
# it will have its working set properly initialized so that it can be written to during a write
435+
# operation that references the branch as a branch-revision database.
436+
@test "sql-server-remotesrv: can write to a branch rev db for a new branch pushed to a sql-server remote" {
437+
mkdir -p db/remote
438+
cd db/remote
439+
dolt init
440+
dolt sql-server --remotesapi-port 50051 --loglevel DEBUG &
441+
srv_pid=$!
442+
cd ../..
443+
444+
# By cloning here, we have a near-at-hand way to wait for the server to be ready.
445+
dolt clone http://localhost:50051/remote cloned_remote
446+
cd cloned_remote
447+
448+
# create a new branch in the clone and push it to the running sql-server
449+
dolt checkout -b new_branch
450+
dolt push origin new_branch
451+
452+
# Check out the new branch, do a test write, and commit
453+
cd ../db/remote
454+
dolt sql -q "CREATE TABLE \`remote/new_branch\`.t123 (pk int primary key);"
455+
run dolt sql -q "SELECT * FROM \`remote/new_branch\`.dolt_status;"
456+
[ "$status" -eq 0 ]
457+
[[ "$output" =~ "t123 | 0 | new table" ]] || false
458+
dolt sql -q "CALL dolt_checkout('new_branch'); CALL dolt_commit('-Am', 'add table t123');"
459+
}
460+
433461
@test "sql-server-remotesrv: push to dirty workspace as super user" {
434462
mkdir remote
435463
cd remote

0 commit comments

Comments
 (0)