Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the dolt_backups table #8872

Merged
merged 4 commits into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion go/libraries/doltcore/doltdb/system_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ var getWriteableSystemTables = func() []string {
}
}

// getGeneratedSystemTables is a function which returns the names of all generated system tables. This is not
// simply a list of constants because doltgres swaps out the functions used to generate different names.
var getGeneratedSystemTables = func() []string {
return []string{
GetBranchesTableName(),
Expand All @@ -218,6 +220,7 @@ var getGeneratedSystemTables = func() []string {
GetStatusTableName(),
GetRemotesTableName(),
GetHelpTableName(),
GetBackupsTableName(),
}
}

Expand Down Expand Up @@ -386,6 +389,10 @@ var GetHelpTableName = func() string {
return HelpTableName
}

var GetBackupsTableName = func() string {
return BackupsTableName
}

const (
// LogTableName is the log system table name
LogTableName = "dolt_log"
Expand Down Expand Up @@ -593,5 +600,6 @@ const (
)

const (
HelpTableName = "dolt_help"
HelpTableName = "dolt_help"
BackupsTableName = "dolt_backups"
)
8 changes: 8 additions & 0 deletions go/libraries/doltcore/sqle/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,14 @@ func (db Database) getTableInsensitive(ctx *sql.Context, head *doltdb.Commit, ds
if !resolve.UseSearchPath || isDoltgresSystemTable {
dt, found = dtables.NewHelpTable(ctx, db.Name(), lwrName), true
}
case doltdb.GetBackupsTableName(), doltdb.BackupsTableName:
isDoltgresSystemTable, err := resolve.IsDoltgresSystemTable(ctx, tname, root)
if err != nil {
return nil, false, err
}
if !resolve.UseSearchPath || isDoltgresSystemTable {
dt, found = dtables.NewBackupsTable(db, lwrName), true
}
}

if found {
Expand Down
117 changes: 117 additions & 0 deletions go/libraries/doltcore/sqle/dtables/backups_table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright 2025 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package dtables

import (
"fmt"
"io"
"sort"

"github.com/dolthub/go-mysql-server/sql"
"github.com/dolthub/go-mysql-server/sql/types"

"github.com/dolthub/dolt/go/libraries/doltcore/env"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/index"
)

type BackupsTable struct {
db dsess.SqlDatabase
tableName string
}

var _ sql.Table = (*BackupsTable)(nil)

func NewBackupsTable(db dsess.SqlDatabase, tableName string) *BackupsTable {
return &BackupsTable{db: db, tableName: tableName}
}

func (bt BackupsTable) Name() string {
return bt.tableName
}

func (bt BackupsTable) String() string {
return bt.tableName
}

func (bt BackupsTable) Schema() sql.Schema {
columns := []*sql.Column{
{Name: "name", Type: types.Text, Source: bt.tableName, PrimaryKey: true, Nullable: false, DatabaseSource: bt.db.Name()},
{Name: "url", Type: types.Text, Source: bt.tableName, PrimaryKey: false, Nullable: false, DatabaseSource: bt.db.Name()},
}
return columns
}

func (bt BackupsTable) Collation() sql.CollationID {
return sql.Collation_Default
}

func (bt BackupsTable) Partitions(context *sql.Context) (sql.PartitionIter, error) {
return index.SinglePartitionIterFromNomsMap(nil), nil
}

func (bt BackupsTable) PartitionRows(context *sql.Context, _ sql.Partition) (sql.RowIter, error) {
return newBackupsIter(context)
}

type backupsItr struct {
names []string
urls map[string]string
idx int
}

var _ sql.RowIter = (*backupsItr)(nil)

func (bi *backupsItr) Next(ctx *sql.Context) (sql.Row, error) {
if bi.idx < len(bi.names) {
bi.idx++
name := bi.names[bi.idx-1]
return sql.NewRow(name, bi.urls[name]), nil
}
return nil, io.EOF
}

func (bi *backupsItr) Close(_ *sql.Context) error { return nil }

func newBackupsIter(ctx *sql.Context) (*backupsItr, error) {
dbName := ctx.GetCurrentDatabase()
if len(dbName) == 0 {
return nil, fmt.Errorf("Empty database name.")
}

sess := dsess.DSessFromSess(ctx.Session)
dbData, ok := sess.GetDbData(ctx, dbName)
if !ok {
return nil, sql.ErrDatabaseNotFound.New(dbName)
}

backups, err := dbData.Rsr.GetBackups()
if err != nil {
return nil, err
}

names := make([]string, 0)
urls := map[string]string{}

backups.Iter(func(key string, val env.Remote) bool {
names = append(names, key)
urls[key] = val.Url
return true
})

sort.Strings(names)

return &backupsItr{names: names, urls: urls, idx: 0}, nil
}
6 changes: 6 additions & 0 deletions go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,12 @@ func TestBrokenSystemTableQueries(t *testing.T) {
enginetest.RunQueryTests(t, h, BrokenSystemTableQueries)
}

func TestBackupsSystemTable(t *testing.T) {
h := newDoltHarness(t)
defer h.Close()
enginetest.TestScript(t, h, BackupsSystemTableQueries)
}

func TestHistorySystemTable(t *testing.T) {
harness := newDoltEnginetestHarness(t).WithParallelism(2)
RunHistorySystemTableTests(t, harness)
Expand Down
1 change: 1 addition & 0 deletions go/libraries/doltcore/sqle/enginetest/dolt_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -7556,6 +7556,7 @@ var DoltSystemVariables = []queries.ScriptTest{
{
Query: "SHOW TABLES;",
Expected: []sql.Row{
{"dolt_backups"},
{"dolt_branches"},
{"dolt_commit_ancestors"},
{"dolt_commit_diff_test"},
Expand Down
51 changes: 51 additions & 0 deletions go/libraries/doltcore/sqle/enginetest/dolt_system_table_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,54 @@ var BrokenSystemTableQueries = []queries.QueryTest{
Expected: []sql.Row{},
},
}

var BackupsSystemTableQueries = queries.ScriptTest{
Name: "dolt_backups table",
SetUpScript: []string{
`call dolt_backup("add", "backup3", "file:///tmp/backup3");`,
`call dolt_backup("add", "backup1", "file:///tmp/backup1");`,
`call dolt_backup("add", "backup2", "aws://[ddb_table:ddb_s3_bucket]/db1");`,
},
Assertions: []queries.ScriptTestAssertion{
{
// Query for just the names because on Windows the Drive letter is inserted into the file path
Query: "select name from dolt_backups;",
Expected: []sql.Row{
{"backup1"},
{"backup2"},
{"backup3"},
},
},
{
Query: "select url from dolt_backups where name = 'backup2';",
Expected: []sql.Row{{"aws://[ddb_table:ddb_s3_bucket]/db1"}},
},
{
Query: "delete from dolt_backups where name = 'backup1';",
ExpectedErrStr: "table doesn't support DELETE FROM",
},
{
Query: "update dolt_backups set name = 'backup1' where name = 'backup2';",
ExpectedErrStr: "table doesn't support UPDATE",
},
{
Query: "insert into dolt_backups values ('backup4', 'file:///tmp/broken');", // nolint: gas
ExpectedErrStr: "table doesn't support INSERT INTO",
},
{
Query: "call dolt_backup('add', 'backup4', 'aws://[ddb_table_4:ddb_s3_bucket_4]/db1');",
Expected: []sql.Row{{0}},
},
{
Query: "call dolt_backup('remove', 'backup1');",
Expected: []sql.Row{{0}},
},
{
Query: "select * from dolt_backups where url like 'aws://%'",
Expected: []sql.Row{
{"backup2", "aws://[ddb_table:ddb_s3_bucket]/db1"},
{"backup4", "aws://[ddb_table_4:ddb_s3_bucket_4]/db1"},
},
},
},
}
3 changes: 2 additions & 1 deletion integration-tests/bats/ls.bats
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ teardown() {
@test "ls: --system shows system tables" {
run dolt ls --system
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 23 ]
[ "${#lines[@]}" -eq 24 ]
[[ "$output" =~ "System tables:" ]] || false
[[ "$output" =~ "dolt_status" ]] || false
[[ "$output" =~ "dolt_commits" ]] || false
Expand All @@ -70,6 +70,7 @@ teardown() {
[[ "$output" =~ "dolt_conflicts" ]] || false
[[ "$output" =~ "dolt_remotes" ]] || false
[[ "$output" =~ "dolt_branches" ]] || false
[[ "$output" =~ "dolt_backups" ]] || false
[[ "$output" =~ "dolt_remote_branches" ]] || false
[[ "$output" =~ "dolt_help" ]] || false
[[ "$output" =~ "dolt_constraint_violations_table_one" ]] || false
Expand Down
Loading