Merge pull request #3994 from dolthub/taylor/use-db-tag

Support `USE` statement with tag name
This commit is contained in:
Taylor Bantle
2022-08-02 17:14:17 -07:00
committed by GitHub
4 changed files with 175 additions and 0 deletions
+16
View File
@@ -726,6 +726,22 @@ func (ddb *DoltDB) GetTags(ctx context.Context) ([]ref.DoltRef, error) {
return ddb.GetRefsOfType(ctx, tagsRefFilter)
}
// HasTag returns whether the DB has a tag with the name given
func (ddb *DoltDB) HasTag(ctx context.Context, tagName string) (bool, error) {
tags, err := ddb.GetRefsOfType(ctx, tagsRefFilter)
if err != nil {
return false, err
}
for _, t := range tags {
if t.GetPath() == tagName {
return true, nil
}
}
return false, nil
}
type TagWithHash struct {
Tag *Tag
Hash hash.Hash
@@ -425,6 +425,40 @@ func (p DoltDatabaseProvider) databaseForRevision(ctx *sql.Context, revDB string
return db, init, true, nil
}
isTag, err := isTag(ctx, srcDb, revSpec, p.remoteDialer)
if err != nil {
return nil, dsess.InitialDbState{}, false, err
}
if isTag {
// TODO: this should be an interface, not a struct
replicaDb, ok := srcDb.(ReadReplicaDatabase)
if ok {
srcDb = replicaDb.Database
}
srcDb, ok = srcDb.(Database)
if !ok {
return nil, dsess.InitialDbState{}, false, nil
}
tag, err := srcDb.(Database).DbData().Ddb.ResolveTag(ctx, ref.NewTagRef(revSpec))
if err != nil {
return nil, dsess.InitialDbState{}, false, err
}
commitHash, err := tag.Commit.HashOf()
if err != nil {
return nil, dsess.InitialDbState{}, false, err
}
db, init, err := dbRevisionForCommit(ctx, srcDb.(Database), commitHash.String())
if err != nil {
return nil, dsess.InitialDbState{}, false, err
}
return db, init, true, nil
}
if doltdb.IsValidCommitHash(revSpec) {
// TODO: this should be an interface, not a struct
replicaDb, ok := srcDb.(ReadReplicaDatabase)
@@ -584,6 +618,36 @@ func isBranch(ctx context.Context, db SqlDatabase, branchName string, dialer dbf
return false, nil
}
// isTag returns whether a tag with the given name is in scope for the database given
func isTag(ctx context.Context, db SqlDatabase, tagName string, dialer dbfactory.GRPCDialProvider) (bool, error) {
var ddbs []*doltdb.DoltDB
if rdb, ok := db.(ReadReplicaDatabase); ok {
remoteDB, err := rdb.remote.GetRemoteDB(ctx, rdb.ddb.Format(), dialer)
if err != nil {
return false, err
}
ddbs = append(ddbs, rdb.ddb, remoteDB)
} else if ddb, ok := db.(Database); ok {
ddbs = append(ddbs, ddb.ddb)
} else {
return false, fmt.Errorf("unrecognized type of database %T", db)
}
for _, ddb := range ddbs {
tagExists, err := ddb.HasTag(ctx, tagName)
if err != nil {
return false, err
}
if tagExists {
return true, nil
}
}
return false, nil
}
func dbRevisionForBranch(ctx context.Context, srcDb SqlDatabase, revSpec string) (SqlDatabase, dsess.InitialDbState, error) {
branch := ref.NewBranchRef(revSpec)
cm, err := srcDb.DbData().Ddb.ResolveCommitRef(ctx, branch)
@@ -316,6 +316,24 @@ teardown() {
server_query repo2 1 "use \`repo2/$head_hash\`" ""
}
@test "remotes-sql-server: connect to tag works" {
skiponwindows "Missing dependencies"
cd repo1
dolt commit -am "cm"
dolt push remote1 main
head_hash=$(get_head_commit)
cd ../repo2
dolt config --local --add sqlserver.global.dolt_read_replica_remote remote1
dolt config --local --add sqlserver.global.dolt_replicate_heads main
dolt tag v1
start_sql_server repo2
server_query repo2 1 "show tables" "Tables_in_repo2\ntest"
server_query repo2 1 "use \`repo2/v1\`" ""
}
get_head_commit() {
dolt log -n 1 | grep -m 1 commit | cut -c 13-44
}
+77
View File
@@ -1606,6 +1606,83 @@ SQL
[[ "$output" =~ 'read-only' ]] || false
}
@test "sql: tag qualified DB name in select" {
dolt add .; dolt commit -m 'commit tables'
dolt checkout -b feature-branch
dolt sql <<SQL
USE \`dolt_repo_$$/feature-branch\`;
CREATE TABLE a1(x int primary key);
insert into a1 values (1), (2), (3);
SELECT DOLT_COMMIT('-a', '-m', 'new table');
SQL
run dolt tag v1
[ "$status" -eq 0 ]
run dolt sql -q "select * from \`dolt_repo_$$/v1\`.a1 order by x;" -r csv
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 4 ]
}
@test "sql: tag qualified DB name in delete" {
dolt add .; dolt commit -m 'commit tables'
dolt checkout -b feature-branch
dolt sql <<SQL
CREATE TABLE a1(x int primary key);
insert into a1 values (1), (2), (3);
SELECT DOLT_COMMIT('-a', '-m', 'new table');
insert into a1 values (4), (5), (6);
select DOLT_COMMIT('-a', '-m', 'more values');
SQL
run dolt tag v1
[ "$status" -eq 0 ]
run dolt sql -q "delete from \`dolt_repo_$$/v1\`.a1;" -r csv
[ "$status" -eq 1 ]
[[ "$output" =~ 'read-only' ]] || false
# same with USE syntax
run dolt sql <<SQL
USE \`dolt_repo_$$/v1\`;
delete from a1;
SQL
[ "$status" -eq 1 ]
[[ "$output" =~ 'read-only' ]] || false
}
@test "sql: tag qualified DB name in update" {
dolt add .; dolt commit -m 'commit tables'
dolt checkout -b feature-branch
dolt sql <<SQL
CREATE TABLE a1(x int primary key);
insert into a1 values (1), (2), (3);
SELECT DOLT_COMMIT('-a', '-m', 'new table');
insert into a1 values (4), (5), (6);
select DOLT_COMMIT('-a', '-m', 'more values');
SQL
run dolt tag v1
[ "$status" -eq 0 ]
run dolt sql -q "update \`dolt_repo_$$/v1\`.a1 set x = x*10" -r csv
[ "$status" -eq 1 ]
[[ "$output" =~ 'read-only' ]] || false
# same with USE syntax
run dolt sql <<SQL
USE \`dolt_repo_$$/v1\`;
update a1 set x = x*10;
SQL
[ "$status" -eq 1 ]
[[ "$output" =~ 'read-only' ]] || false
}
@test "sql: describe" {
run dolt sql -q "describe one_pk"
[ $status -eq 0 ]