From 4a55a112164536c4744af68ced969ba3d4969458 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Tue, 2 Aug 2022 12:17:12 -0700 Subject: [PATCH] Add tags to databaseForRevision --- go/libraries/doltcore/doltdb/doltdb.go | 16 ++++ .../doltcore/sqle/database_provider.go | 64 +++++++++++++++ .../bats/remotes-sql-server.bats | 18 +++++ integration-tests/bats/sql.bats | 77 +++++++++++++++++++ 4 files changed, 175 insertions(+) diff --git a/go/libraries/doltcore/doltdb/doltdb.go b/go/libraries/doltcore/doltdb/doltdb.go index 9f389acf18..2d8ce9245e 100644 --- a/go/libraries/doltcore/doltdb/doltdb.go +++ b/go/libraries/doltcore/doltdb/doltdb.go @@ -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 diff --git a/go/libraries/doltcore/sqle/database_provider.go b/go/libraries/doltcore/sqle/database_provider.go index ded18ef172..652626e097 100644 --- a/go/libraries/doltcore/sqle/database_provider.go +++ b/go/libraries/doltcore/sqle/database_provider.go @@ -381,6 +381,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) @@ -540,6 +574,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) diff --git a/integration-tests/bats/remotes-sql-server.bats b/integration-tests/bats/remotes-sql-server.bats index d2f2a7380b..d41f25b65e 100644 --- a/integration-tests/bats/remotes-sql-server.bats +++ b/integration-tests/bats/remotes-sql-server.bats @@ -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 } diff --git a/integration-tests/bats/sql.bats b/integration-tests/bats/sql.bats index d5cfb9cda9..61117f2ba2 100755 --- a/integration-tests/bats/sql.bats +++ b/integration-tests/bats/sql.bats @@ -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 <