From e9354f6ce52f8a88307d94345789de0d5c3dd5dd Mon Sep 17 00:00:00 2001 From: Nick Tobey Date: Mon, 16 Oct 2023 16:33:05 -0700 Subject: [PATCH 1/5] Add VersionedTable interface. --- go/libraries/doltcore/sqle/database.go | 37 ++++++++----------- .../doltcore/sqle/dtables/ignore_table.go | 26 ++++++++++--- .../doltcore/sqle/dtables/versioned_table.go | 26 +++++++++++++ go/libraries/doltcore/sqle/history_table.go | 12 +++--- go/libraries/doltcore/sqle/tables.go | 5 ++- 5 files changed, 73 insertions(+), 33 deletions(-) create mode 100644 go/libraries/doltcore/sqle/dtables/versioned_table.go diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index 7c2b745feb..9df90e61ba 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -275,28 +275,18 @@ func (db Database) GetTableInsensitiveAsOf(ctx *sql.Context, tableName string, a return table, ok, nil } - switch table := table.(type) { - case *DoltTable: - tbl, err := table.LockedToRoot(ctx, root) - if err != nil { - return nil, false, err - } - return tbl, true, nil - case *AlterableDoltTable: - tbl, err := table.LockedToRoot(ctx, root) - if err != nil { - return nil, false, err - } - return tbl, true, nil - case *WritableDoltTable: - tbl, err := table.LockedToRoot(ctx, root) - if err != nil { - return nil, false, err - } - return tbl, true, nil - default: + lockableTable, ok := table.(dtables.VersionedTable) + if !ok { panic(fmt.Sprintf("unexpected table type %T", table)) } + + versionedTable, err := lockableTable.LockedToRoot(ctx, root) + + if err != nil { + return nil, false, err + } + return versionedTable, true, nil + } func (db Database) getTableInsensitive(ctx *sql.Context, head *doltdb.Commit, ds *dsess.DoltSession, root *doltdb.RootValue, tblName string) (sql.Table, bool, error) { @@ -457,7 +447,12 @@ func (db Database) getTableInsensitive(ctx *sql.Context, head *doltdb.Commit, ds if err != nil { return nil, false, err } - dt, found = dtables.NewIgnoreTable(ctx, db.ddb, backingTable), true + lockableTable, ok := backingTable.(dtables.VersionedTable) + if !ok { + // check for nil + dt, found = dtables.NewIgnoreTable(ctx, nil), true + } + dt, found = dtables.NewIgnoreTable(ctx, lockableTable), true } if found { diff --git a/go/libraries/doltcore/sqle/dtables/ignore_table.go b/go/libraries/doltcore/sqle/dtables/ignore_table.go index 79202e6919..b43e96698a 100644 --- a/go/libraries/doltcore/sqle/dtables/ignore_table.go +++ b/go/libraries/doltcore/sqle/dtables/ignore_table.go @@ -16,7 +16,6 @@ package dtables import ( "fmt" - "github.com/dolthub/go-mysql-server/sql" sqlTypes "github.com/dolthub/go-mysql-server/sql/types" @@ -38,8 +37,7 @@ var _ sql.ReplaceableTable = (*IgnoreTable)(nil) // IgnoreTable is the system table that stores patterns for table names that should not be committed. type IgnoreTable struct { - ddb *doltdb.DoltDB - backingTable sql.Table + backingTable VersionedTable } func (i *IgnoreTable) Name() string { @@ -81,8 +79,8 @@ func (i *IgnoreTable) PartitionRows(context *sql.Context, partition sql.Partitio } // NewIgnoreTable creates an IgnoreTable -func NewIgnoreTable(_ *sql.Context, ddb *doltdb.DoltDB, backingTable sql.Table) sql.Table { - return &IgnoreTable{ddb: ddb, backingTable: backingTable} +func NewIgnoreTable(_ *sql.Context, backingTable VersionedTable) sql.Table { + return &IgnoreTable{backingTable: backingTable} } // Replacer returns a RowReplacer for this table. The RowReplacer will have Insert and optionally Delete called once @@ -109,6 +107,24 @@ func (it *IgnoreTable) Deleter(*sql.Context) sql.RowDeleter { return newIgnoreWriter(it) } +func (it *IgnoreTable) LockedToRoot(ctx *sql.Context, root *doltdb.RootValue) (sql.IndexAddressableTable, error) { + if it.backingTable == nil { + return it, nil + } + return it.backingTable.LockedToRoot(ctx, root) +} + +// IndexedAccess implements IndexAddressableTable, but IgnoreTables has no indexes. +// Thus, this should never be called. +func (it *IgnoreTable) IndexedAccess(lookup sql.IndexLookup) sql.IndexedTable { + panic("Unreachable") +} + +// GetIndexes implements IndexAddressableTable, but IgnoreTables has no indexes. +func (it *IgnoreTable) GetIndexes(ctx *sql.Context) ([]sql.Index, error) { + return nil, nil +} + var _ sql.RowReplacer = (*ignoreWriter)(nil) var _ sql.RowUpdater = (*ignoreWriter)(nil) var _ sql.RowInserter = (*ignoreWriter)(nil) diff --git a/go/libraries/doltcore/sqle/dtables/versioned_table.go b/go/libraries/doltcore/sqle/dtables/versioned_table.go new file mode 100644 index 0000000000..f9889c4b43 --- /dev/null +++ b/go/libraries/doltcore/sqle/dtables/versioned_table.go @@ -0,0 +1,26 @@ +// Copyright 2023 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 ( + "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" + "github.com/dolthub/go-mysql-server/sql" +) + +// VersionedTable is a sql.Table that has a history. The history can be queried by setting a specific doltdb.RootValue. +type VersionedTable interface { + sql.Table + LockedToRoot(ctx *sql.Context, root *doltdb.RootValue) (sql.IndexAddressableTable, error) +} diff --git a/go/libraries/doltcore/sqle/history_table.go b/go/libraries/doltcore/sqle/history_table.go index bec320ea16..afb2aae45d 100644 --- a/go/libraries/doltcore/sqle/history_table.go +++ b/go/libraries/doltcore/sqle/history_table.go @@ -489,7 +489,7 @@ func newRowItrForTableAtCommit(ctx *sql.Context, table *DoltTable, h hash.Hash, return &historyIter{nonExistentTable: true}, nil } - table, err = table.LockedToRoot(ctx, root) + lockedTable, err := table.LockedToRoot(ctx, root) if err != nil { return nil, err } @@ -497,13 +497,13 @@ func newRowItrForTableAtCommit(ctx *sql.Context, table *DoltTable, h hash.Hash, var partIter sql.PartitionIter var histTable sql.Table if !lookup.IsEmpty() { - indexes, err := table.GetIndexes(ctx) + indexes, err := lockedTable.GetIndexes(ctx) if err != nil { return nil, err } for _, idx := range indexes { if idx.ID() == lookup.Index.ID() { - histTable = table.IndexedAccess(lookup) + histTable = lockedTable.IndexedAccess(lookup) if err != nil { return nil, err } @@ -520,14 +520,14 @@ func newRowItrForTableAtCommit(ctx *sql.Context, table *DoltTable, h hash.Hash, } } if histTable == nil { - histTable = table - partIter, err = table.Partitions(ctx) + histTable = lockedTable + partIter, err = lockedTable.Partitions(ctx) if err != nil { return nil, err } } - converter := rowConverter(table.Schema(), targetSchema, h, meta, projections) + converter := rowConverter(lockedTable.Schema(), targetSchema, h, meta, projections) return &historyIter{ table: histTable, tablePartitions: partIter, diff --git a/go/libraries/doltcore/sqle/tables.go b/go/libraries/doltcore/sqle/tables.go index 545aa4b78b..80d3a9e502 100644 --- a/go/libraries/doltcore/sqle/tables.go +++ b/go/libraries/doltcore/sqle/tables.go @@ -19,6 +19,7 @@ import ( "context" "errors" "fmt" + "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dtables" "io" "math" "os" @@ -74,6 +75,8 @@ func init() { } } +var _ dtables.VersionedTable = (*DoltTable)(nil) + // DoltTable implements the sql.Table interface and gives access to dolt table rows and schema. type DoltTable struct { tableName string @@ -120,7 +123,7 @@ func NewDoltTable(name string, sch schema.Schema, tbl *doltdb.Table, db dsess.Sq // LockedToRoot returns a version of this table with its root value locked to the given value. The table's values will // not change as the session's root value changes. Appropriate for AS OF queries, or other use cases where the table's // values should not change throughout execution of a session. -func (t *DoltTable) LockedToRoot(ctx *sql.Context, root *doltdb.RootValue) (*DoltTable, error) { +func (t *DoltTable) LockedToRoot(ctx *sql.Context, root *doltdb.RootValue) (sql.IndexAddressableTable, error) { tbl, ok, err := root.GetTable(ctx, t.tableName) if err != nil { return nil, err From e6f6a0555f0b72d6f6758859ebd25079289aa511 Mon Sep 17 00:00:00 2001 From: Nick Tobey Date: Mon, 16 Oct 2023 16:40:33 -0700 Subject: [PATCH 2/5] Rename interface to VersionableTable, plus other cleanups. --- go/libraries/doltcore/sqle/database.go | 13 ++++++------- go/libraries/doltcore/sqle/dtables/ignore_table.go | 9 +++++++-- .../doltcore/sqle/dtables/versioned_table.go | 4 ++-- go/libraries/doltcore/sqle/tables.go | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index 9df90e61ba..aa2036a51f 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -275,12 +275,12 @@ func (db Database) GetTableInsensitiveAsOf(ctx *sql.Context, tableName string, a return table, ok, nil } - lockableTable, ok := table.(dtables.VersionedTable) + versionableTable, ok := table.(dtables.VersionableTable) if !ok { panic(fmt.Sprintf("unexpected table type %T", table)) } - versionedTable, err := lockableTable.LockedToRoot(ctx, root) + versionedTable, err := versionableTable.LockedToRoot(ctx, root) if err != nil { return nil, false, err @@ -447,12 +447,11 @@ func (db Database) getTableInsensitive(ctx *sql.Context, head *doltdb.Commit, ds if err != nil { return nil, false, err } - lockableTable, ok := backingTable.(dtables.VersionedTable) - if !ok { - // check for nil - dt, found = dtables.NewIgnoreTable(ctx, nil), true + if backingTable == nil { + dt, found = dtables.NewEmptyIgnoreTable(ctx), true } - dt, found = dtables.NewIgnoreTable(ctx, lockableTable), true + versionableTable := backingTable.(dtables.VersionableTable) + dt, found = dtables.NewIgnoreTable(ctx, versionableTable), true } if found { diff --git a/go/libraries/doltcore/sqle/dtables/ignore_table.go b/go/libraries/doltcore/sqle/dtables/ignore_table.go index b43e96698a..446905c68e 100644 --- a/go/libraries/doltcore/sqle/dtables/ignore_table.go +++ b/go/libraries/doltcore/sqle/dtables/ignore_table.go @@ -37,7 +37,7 @@ var _ sql.ReplaceableTable = (*IgnoreTable)(nil) // IgnoreTable is the system table that stores patterns for table names that should not be committed. type IgnoreTable struct { - backingTable VersionedTable + backingTable VersionableTable } func (i *IgnoreTable) Name() string { @@ -79,10 +79,15 @@ func (i *IgnoreTable) PartitionRows(context *sql.Context, partition sql.Partitio } // NewIgnoreTable creates an IgnoreTable -func NewIgnoreTable(_ *sql.Context, backingTable VersionedTable) sql.Table { +func NewIgnoreTable(_ *sql.Context, backingTable VersionableTable) sql.Table { return &IgnoreTable{backingTable: backingTable} } +// NewEmptyIgnoreTable creates an IgnoreTable +func NewEmptyIgnoreTable(_ *sql.Context) sql.Table { + return &IgnoreTable{} +} + // Replacer returns a RowReplacer for this table. The RowReplacer will have Insert and optionally Delete called once // for each row, followed by a call to Close() when all rows have been processed. func (it *IgnoreTable) Replacer(ctx *sql.Context) sql.RowReplacer { diff --git a/go/libraries/doltcore/sqle/dtables/versioned_table.go b/go/libraries/doltcore/sqle/dtables/versioned_table.go index f9889c4b43..b0b9dc0d9c 100644 --- a/go/libraries/doltcore/sqle/dtables/versioned_table.go +++ b/go/libraries/doltcore/sqle/dtables/versioned_table.go @@ -19,8 +19,8 @@ import ( "github.com/dolthub/go-mysql-server/sql" ) -// VersionedTable is a sql.Table that has a history. The history can be queried by setting a specific doltdb.RootValue. -type VersionedTable interface { +// VersionableTable is a sql.Table that has a history. The history can be queried by setting a specific doltdb.RootValue. +type VersionableTable interface { sql.Table LockedToRoot(ctx *sql.Context, root *doltdb.RootValue) (sql.IndexAddressableTable, error) } diff --git a/go/libraries/doltcore/sqle/tables.go b/go/libraries/doltcore/sqle/tables.go index 80d3a9e502..02e6c9419a 100644 --- a/go/libraries/doltcore/sqle/tables.go +++ b/go/libraries/doltcore/sqle/tables.go @@ -75,7 +75,7 @@ func init() { } } -var _ dtables.VersionedTable = (*DoltTable)(nil) +var _ dtables.VersionableTable = (*DoltTable)(nil) // DoltTable implements the sql.Table interface and gives access to dolt table rows and schema. type DoltTable struct { From 6721bf6eba6bfcdef1915877501760cea6b43ce1 Mon Sep 17 00:00:00 2001 From: nicktobey Date: Mon, 16 Oct 2023 23:50:29 +0000 Subject: [PATCH 3/5] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- go/libraries/doltcore/sqle/dtables/ignore_table.go | 1 + go/libraries/doltcore/sqle/dtables/versioned_table.go | 3 ++- go/libraries/doltcore/sqle/tables.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/go/libraries/doltcore/sqle/dtables/ignore_table.go b/go/libraries/doltcore/sqle/dtables/ignore_table.go index 446905c68e..6c75339ab0 100644 --- a/go/libraries/doltcore/sqle/dtables/ignore_table.go +++ b/go/libraries/doltcore/sqle/dtables/ignore_table.go @@ -16,6 +16,7 @@ package dtables import ( "fmt" + "github.com/dolthub/go-mysql-server/sql" sqlTypes "github.com/dolthub/go-mysql-server/sql/types" diff --git a/go/libraries/doltcore/sqle/dtables/versioned_table.go b/go/libraries/doltcore/sqle/dtables/versioned_table.go index b0b9dc0d9c..44d4aab140 100644 --- a/go/libraries/doltcore/sqle/dtables/versioned_table.go +++ b/go/libraries/doltcore/sqle/dtables/versioned_table.go @@ -15,8 +15,9 @@ package dtables import ( - "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/go-mysql-server/sql" + + "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" ) // VersionableTable is a sql.Table that has a history. The history can be queried by setting a specific doltdb.RootValue. diff --git a/go/libraries/doltcore/sqle/tables.go b/go/libraries/doltcore/sqle/tables.go index 02e6c9419a..45b002f94f 100644 --- a/go/libraries/doltcore/sqle/tables.go +++ b/go/libraries/doltcore/sqle/tables.go @@ -19,7 +19,6 @@ import ( "context" "errors" "fmt" - "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dtables" "io" "math" "os" @@ -40,6 +39,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/schema" "github.com/dolthub/dolt/go/libraries/doltcore/schema/typeinfo" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" + "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dtables" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/index" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlutil" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/writer" From 40926d2db0190a0d5ff88e13e838062a5aef0b24 Mon Sep 17 00:00:00 2001 From: Nick Tobey Date: Mon, 16 Oct 2023 17:04:11 -0700 Subject: [PATCH 4/5] Fix control flow in `Database::getTableInsensitive` --- go/libraries/doltcore/sqle/database.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index aa2036a51f..47348eeb6c 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -449,9 +449,10 @@ func (db Database) getTableInsensitive(ctx *sql.Context, head *doltdb.Commit, ds } if backingTable == nil { dt, found = dtables.NewEmptyIgnoreTable(ctx), true + } else { + versionableTable := backingTable.(dtables.VersionableTable) + dt, found = dtables.NewIgnoreTable(ctx, versionableTable), true } - versionableTable := backingTable.(dtables.VersionableTable) - dt, found = dtables.NewIgnoreTable(ctx, versionableTable), true } if found { From c3a827c8a8c197402fa955274d667dfecb80e014 Mon Sep 17 00:00:00 2001 From: Nick Tobey Date: Mon, 16 Oct 2023 17:04:20 -0700 Subject: [PATCH 5/5] Add BATS tests for `dolt_ignore AS OF` --- integration-tests/bats/ignore.bats | 327 +++-------------------------- 1 file changed, 33 insertions(+), 294 deletions(-) diff --git a/integration-tests/bats/ignore.bats b/integration-tests/bats/ignore.bats index ca68840580..267a57893e 100644 --- a/integration-tests/bats/ignore.bats +++ b/integration-tests/bats/ignore.bats @@ -63,325 +63,64 @@ get_conflict_tables() { ' } -@test "ignore: simple matches" { - dolt sql <