mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-05 02:59:44 -06:00
Merge pull request #10227 from codeaucafe/codeaucafe/5862/make-ignore-system-table
dolthub/dolt#5862: Add ignore system table
This commit is contained in:
@@ -162,6 +162,7 @@ func GeneratedSystemTableNames() []string {
|
||||
GetBranchActivityTableName(),
|
||||
// [dtables.StatusTable] now uses [adapters.DoltTableAdapterRegistry] in its constructor for Doltgres.
|
||||
StatusTableName,
|
||||
StatusIgnoredTableName,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,6 +436,9 @@ const (
|
||||
// StatusTableName is the status system table name.
|
||||
StatusTableName = "dolt_status"
|
||||
|
||||
// StatusIgnoredTableName is the status_ignored system table name.
|
||||
StatusIgnoredTableName = "dolt_status_ignored"
|
||||
|
||||
// MergeStatusTableName is the merge status system table name.
|
||||
MergeStatusTableName = "dolt_merge_status"
|
||||
|
||||
@@ -477,6 +481,7 @@ var DoltGeneratedTableNames = []string{
|
||||
CommitsTableName,
|
||||
CommitAncestorsTableName,
|
||||
StatusTableName,
|
||||
StatusIgnoredTableName,
|
||||
MergeStatusTableName,
|
||||
TagsTableName,
|
||||
}
|
||||
|
||||
@@ -758,59 +758,24 @@ func (db Database) getTableInsensitiveWithRoot(ctx *sql.Context, head *doltdb.Co
|
||||
return nil, false, err
|
||||
}
|
||||
if !resolve.UseSearchPath || isDoltgresSystemTable {
|
||||
sess := dsess.DSessFromSess(ctx.Session)
|
||||
var rootsProvider env.RootsProvider[*sql.Context]
|
||||
rootsProvider = dsess.NewSessionStateAdapter(
|
||||
sess, db.RevisionQualifiedName(),
|
||||
concurrentmap.New[string, env.Remote](),
|
||||
concurrentmap.New[string, env.BranchConfig](),
|
||||
concurrentmap.New[string, env.Remote]())
|
||||
ws, err := sess.WorkingSet(ctx, db.RevisionQualifiedName())
|
||||
rootsProvider, ws, err := getStatusTableRootsProvider(ctx, db, ds, asOf)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
asOf, ok := asOf.(string)
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf(
|
||||
"unexpected type for asOf param: %T", asOf)
|
||||
}
|
||||
|
||||
// If |asOf| is set, then we need to get the correct roots for the
|
||||
// status table to use. We skip the special revision spec, HEAD,
|
||||
// because it represents the current branch.
|
||||
if asOf != "" && !strings.EqualFold(asOf, "HEAD") {
|
||||
// If |asOf| is a branch name, then grab the working set for that
|
||||
// branch and use its data.
|
||||
ddb, ok := ds.GetDoltDB(ctx, ctx.GetCurrentDatabase())
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf(
|
||||
"unable to get DoltDB for database %s", ctx.GetCurrentDatabase())
|
||||
}
|
||||
|
||||
_, hasBranch, err := ddb.HasBranch(ctx, asOf)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if hasBranch {
|
||||
branchRoots, err := getRootsForBranch(ctx, ddb, asOf)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
rootsProvider = &staticRootsProvider{
|
||||
roots: branchRoots,
|
||||
}
|
||||
} else {
|
||||
// If this isn't a branch, then it's a tag or a commit, or a
|
||||
// commit spec. In all of these cases, dolt_status will have
|
||||
// no data, because there is no valid head/working/staged roots,
|
||||
// so we provide a nil rootsProvider
|
||||
rootsProvider = nil
|
||||
}
|
||||
}
|
||||
|
||||
dt, found = dtables.NewStatusTable(ctx, lwrName, db.ddb, ws, rootsProvider), true
|
||||
}
|
||||
case doltdb.StatusIgnoredTableName:
|
||||
isDoltgresSystemTable, err := resolve.IsDoltgresSystemTable(ctx, tname, root)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if !resolve.UseSearchPath || isDoltgresSystemTable {
|
||||
rootsProvider, ws, err := getStatusTableRootsProvider(ctx, db, ds, asOf)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
dt, found = dtables.NewStatusIgnoredTable(ctx, lwrName, db.ddb, ws, rootsProvider), true
|
||||
}
|
||||
case doltdb.MergeStatusTableName, doltdb.GetMergeStatusTableName():
|
||||
isDoltgresSystemTable, err := resolve.IsDoltgresSystemTable(ctx, tname, root)
|
||||
if err != nil {
|
||||
@@ -1296,6 +1261,68 @@ func (srp *staticRootsProvider) GetRoots(ctx *sql.Context) (doltdb.Roots, error)
|
||||
|
||||
var _ env.RootsProvider[*sql.Context] = (*staticRootsProvider)(nil)
|
||||
|
||||
// getStatusTableRootsProvider returns the roots provider and working set needed for status tables
|
||||
// (dolt_status and dolt_status_ignored). This handles the asOf parameter to support querying status
|
||||
// for different branches, tags, or commits.
|
||||
func getStatusTableRootsProvider(
|
||||
ctx *sql.Context,
|
||||
db Database,
|
||||
ds *dsess.DoltSession,
|
||||
asOf interface{},
|
||||
) (env.RootsProvider[*sql.Context], *doltdb.WorkingSet, error) {
|
||||
sess := dsess.DSessFromSess(ctx.Session)
|
||||
var rootsProvider env.RootsProvider[*sql.Context]
|
||||
rootsProvider = dsess.NewSessionStateAdapter(
|
||||
sess, db.RevisionQualifiedName(),
|
||||
concurrentmap.New[string, env.Remote](),
|
||||
concurrentmap.New[string, env.BranchConfig](),
|
||||
concurrentmap.New[string, env.Remote]())
|
||||
ws, err := sess.WorkingSet(ctx, db.RevisionQualifiedName())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
asOfStr, ok := asOf.(string)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("unexpected type for asOf param: %T", asOf)
|
||||
}
|
||||
|
||||
// If |asOf| is set, then we need to get the correct roots for the
|
||||
// status table to use. We skip the special revision spec, HEAD,
|
||||
// because it represents the current branch.
|
||||
if asOfStr != "" && !strings.EqualFold(asOfStr, "HEAD") {
|
||||
// If |asOf| is a branch name, then grab the working set for that
|
||||
// branch and use its data.
|
||||
ddb, ok := ds.GetDoltDB(ctx, ctx.GetCurrentDatabase())
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf(
|
||||
"unable to get DoltDB for database %s", ctx.GetCurrentDatabase())
|
||||
}
|
||||
|
||||
_, hasBranch, err := ddb.HasBranch(ctx, asOfStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if hasBranch {
|
||||
branchRoots, err := getRootsForBranch(ctx, ddb, asOfStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
rootsProvider = &staticRootsProvider{
|
||||
roots: branchRoots,
|
||||
}
|
||||
} else {
|
||||
// If this isn't a branch, then it's a tag or a commit, or a
|
||||
// commit spec. In all of these cases, the status table will have
|
||||
// no data, because there is no valid head/working/staged roots,
|
||||
// so we provide a nil rootsProvider
|
||||
rootsProvider = nil
|
||||
}
|
||||
}
|
||||
|
||||
return rootsProvider, ws, nil
|
||||
}
|
||||
|
||||
// workingSetStagedRoot returns the staged root for the current session in the database
|
||||
// named |dbName|. If a working set is not available (e.g. if a commit or tag is checked
|
||||
// out), this function returns an ErrOperationNotSupportedInDetachedHead error.
|
||||
|
||||
204
go/libraries/doltcore/sqle/dtables/status_ignored_table.go
Normal file
204
go/libraries/doltcore/sqle/dtables/status_ignored_table.go
Normal file
@@ -0,0 +1,204 @@
|
||||
// Copyright 2026 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 (
|
||||
"io"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
"github.com/dolthub/go-mysql-server/sql/types"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/diff"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/adapters"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/index"
|
||||
)
|
||||
|
||||
const statusIgnoredDefaultRowCount = 10
|
||||
|
||||
// StatusIgnoredTable is a sql.Table implementation that shows status including ignored tables.
|
||||
// This is the SQL equivalent of `dolt status --ignored`.
|
||||
type StatusIgnoredTable struct {
|
||||
rootsProvider env.RootsProvider[*sql.Context]
|
||||
ddb *doltdb.DoltDB
|
||||
workingSet *doltdb.WorkingSet
|
||||
tableName string
|
||||
}
|
||||
|
||||
var _ sql.StatisticsTable = (*StatusIgnoredTable)(nil)
|
||||
|
||||
func (st StatusIgnoredTable) DataLength(ctx *sql.Context) (uint64, error) {
|
||||
numBytesPerRow := schema.SchemaAvgLength(st.Schema())
|
||||
numRows, _, err := st.RowCount(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return numBytesPerRow * numRows, nil
|
||||
}
|
||||
|
||||
func (st StatusIgnoredTable) RowCount(_ *sql.Context) (uint64, bool, error) {
|
||||
return statusIgnoredDefaultRowCount, false, nil
|
||||
}
|
||||
|
||||
func (st StatusIgnoredTable) Name() string {
|
||||
return st.tableName
|
||||
}
|
||||
|
||||
func (st StatusIgnoredTable) String() string {
|
||||
return st.tableName
|
||||
}
|
||||
|
||||
func (st StatusIgnoredTable) Schema() sql.Schema {
|
||||
return []*sql.Column{
|
||||
{Name: "table_name", Type: types.Text, Source: doltdb.StatusIgnoredTableName, PrimaryKey: true, Nullable: false},
|
||||
{Name: "staged", Type: types.Boolean, Source: doltdb.StatusIgnoredTableName, PrimaryKey: true, Nullable: false},
|
||||
{Name: "status", Type: types.Text, Source: doltdb.StatusIgnoredTableName, PrimaryKey: true, Nullable: false},
|
||||
{Name: "ignored", Type: types.Boolean, Source: doltdb.StatusIgnoredTableName, PrimaryKey: false, Nullable: false},
|
||||
}
|
||||
}
|
||||
|
||||
func (st StatusIgnoredTable) Collation() sql.CollationID {
|
||||
return sql.Collation_Default
|
||||
}
|
||||
|
||||
func (st StatusIgnoredTable) Partitions(*sql.Context) (sql.PartitionIter, error) {
|
||||
return index.SinglePartitionIterFromNomsMap(nil), nil
|
||||
}
|
||||
|
||||
func (st StatusIgnoredTable) PartitionRows(context *sql.Context, _ sql.Partition) (sql.RowIter, error) {
|
||||
return newStatusIgnoredItr(context, &st)
|
||||
}
|
||||
|
||||
// NewStatusIgnoredTable creates a new StatusIgnoredTable using either an integrators' [adapters.TableAdapter] or the
|
||||
// NewStatusIgnoredTableWithNoAdapter constructor (the default implementation provided by Dolt).
|
||||
func NewStatusIgnoredTable(ctx *sql.Context, tableName string, ddb *doltdb.DoltDB, ws *doltdb.WorkingSet, rp env.RootsProvider[*sql.Context]) sql.Table {
|
||||
adapter, ok := adapters.DoltTableAdapterRegistry.GetAdapter(tableName)
|
||||
if ok {
|
||||
return adapter.NewTable(ctx, tableName, ddb, ws, rp)
|
||||
}
|
||||
|
||||
return NewStatusIgnoredTableWithNoAdapter(ctx, tableName, ddb, ws, rp)
|
||||
}
|
||||
|
||||
// NewStatusIgnoredTableWithNoAdapter returns a new StatusIgnoredTable.
|
||||
func NewStatusIgnoredTableWithNoAdapter(_ *sql.Context, tableName string, ddb *doltdb.DoltDB, ws *doltdb.WorkingSet, rp env.RootsProvider[*sql.Context]) sql.Table {
|
||||
return &StatusIgnoredTable{
|
||||
tableName: tableName,
|
||||
ddb: ddb,
|
||||
workingSet: ws,
|
||||
rootsProvider: rp,
|
||||
}
|
||||
}
|
||||
|
||||
// StatusIgnoredItr is a sql.RowIter implementation for the status_ignored table.
|
||||
type StatusIgnoredItr struct {
|
||||
rows []statusIgnoredTableRow
|
||||
}
|
||||
|
||||
type statusIgnoredTableRow struct {
|
||||
tableName string
|
||||
status string
|
||||
isStaged byte // not a bool bc wire protocol confuses bools and tinyint(1)
|
||||
ignored bool
|
||||
}
|
||||
|
||||
func newStatusIgnoredItr(ctx *sql.Context, st *StatusIgnoredTable) (*StatusIgnoredItr, error) {
|
||||
// If no roots provider was set, then there is no status to report
|
||||
if st.rootsProvider == nil {
|
||||
return &StatusIgnoredItr{rows: nil}, nil
|
||||
}
|
||||
|
||||
// Get the base status data using the shared function
|
||||
statusRows, unstagedTables, err := getStatusRowsData(ctx, st.rootsProvider, st.workingSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get ignore patterns for checking if unstaged tables are ignored
|
||||
ignorePatterns, err := getIgnorePatterns(ctx, st.rootsProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build a set of unstaged table names for quick lookup
|
||||
unstagedTableNames := buildUnstagedTableNameSet(unstagedTables)
|
||||
|
||||
// Convert status rows to status_ignored rows, adding the ignored column
|
||||
rows := make([]statusIgnoredTableRow, len(statusRows))
|
||||
for i, row := range statusRows {
|
||||
ignored := false
|
||||
// Only check ignore patterns for unstaged NEW tables (same as Git behavior).
|
||||
// Tables that are modified, deleted, or renamed are already tracked,
|
||||
// so ignore patterns don't apply to them.
|
||||
if row.isStaged == byte(0) && row.status == newTableStatus && unstagedTableNames[row.tableName] {
|
||||
tblNameObj := doltdb.TableName{Name: row.tableName}
|
||||
result, err := ignorePatterns.IsTableNameIgnored(tblNameObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result == doltdb.Ignore {
|
||||
ignored = true
|
||||
}
|
||||
}
|
||||
rows[i] = statusIgnoredTableRow{
|
||||
tableName: row.tableName,
|
||||
isStaged: row.isStaged,
|
||||
status: row.status,
|
||||
ignored: ignored,
|
||||
}
|
||||
}
|
||||
|
||||
return &StatusIgnoredItr{rows: rows}, nil
|
||||
}
|
||||
|
||||
// getIgnorePatterns fetches the ignore patterns from the roots provider.
|
||||
func getIgnorePatterns(ctx *sql.Context, rp env.RootsProvider[*sql.Context]) (doltdb.IgnorePatterns, error) {
|
||||
roots, err := rp.GetRoots(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
schemas := []string{doltdb.DefaultSchemaName}
|
||||
ignorePatternMap, err := doltdb.GetIgnoredTablePatterns(ctx, roots, schemas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ignorePatternMap[doltdb.DefaultSchemaName], nil
|
||||
}
|
||||
|
||||
// buildUnstagedTableNameSet builds a set of unstaged table names for quick lookup.
|
||||
func buildUnstagedTableNameSet(unstagedTables []diff.TableDelta) map[string]bool {
|
||||
result := make(map[string]bool, len(unstagedTables))
|
||||
for _, td := range unstagedTables {
|
||||
result[td.CurName()] = true
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Next retrieves the next row. It will return io.EOF if it's the last row.
|
||||
func (itr *StatusIgnoredItr) Next(*sql.Context) (sql.Row, error) {
|
||||
if len(itr.rows) <= 0 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
row := itr.rows[0]
|
||||
itr.rows = itr.rows[1:]
|
||||
return sql.NewRow(row.tableName, row.isStaged, row.status, row.ignored), nil
|
||||
}
|
||||
|
||||
// Close closes the iterator.
|
||||
func (itr *StatusIgnoredItr) Close(*sql.Context) error {
|
||||
return nil
|
||||
}
|
||||
@@ -115,6 +115,7 @@ type statusTableRow struct {
|
||||
// of this table when you are using local vs remote sql connections.
|
||||
}
|
||||
|
||||
// containsTableName checks if a table name is in the list of table names.
|
||||
func containsTableName(name string, names []doltdb.TableName) bool {
|
||||
for _, s := range names {
|
||||
if s.String() == name {
|
||||
@@ -124,21 +125,26 @@ func containsTableName(name string, names []doltdb.TableName) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) {
|
||||
// If no roots provider was set, then there is no status to report
|
||||
rp := st.rootsProvider
|
||||
// getStatusRowsData collects all status data from the given roots and working set.
|
||||
// This is the shared logic used by both dolt_status and dolt_status_ignored tables.
|
||||
// Returns the rows data along with the unstaged table deltas (needed for ignore checking).
|
||||
func getStatusRowsData(
|
||||
ctx *sql.Context,
|
||||
rp env.RootsProvider[*sql.Context],
|
||||
ws *doltdb.WorkingSet,
|
||||
) ([]statusTableRow, []diff.TableDelta, error) {
|
||||
if rp == nil {
|
||||
return &StatusItr{rows: nil}, nil
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
roots, err := rp.GetRoots(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
stagedTables, unstagedTables, err := diff.GetStagedUnstagedTableDeltas(ctx, roots)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Some tables may differ only in column tags and/or recorded conflicts.
|
||||
@@ -147,7 +153,7 @@ func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) {
|
||||
for _, unstagedTableDiff := range unstagedTables {
|
||||
changed, err := unstagedTableDiff.HasChangesIgnoringColumnTags(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if changed {
|
||||
changedUnstagedTables = append(changedUnstagedTables, unstagedTableDiff)
|
||||
@@ -157,30 +163,30 @@ func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) {
|
||||
|
||||
stagedSchemas, unstagedSchemas, err := diff.GetStagedUnstagedDatabaseSchemaDeltas(ctx, roots)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
rows := make([]statusTableRow, 0, len(stagedTables)+len(unstagedTables)+len(stagedSchemas)+len(unstagedSchemas))
|
||||
|
||||
cvTables, err := doltdb.TablesWithConstraintViolations(ctx, roots.Working)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for _, tbl := range cvTables {
|
||||
rows = append(rows, statusTableRow{
|
||||
tableName: tbl.String(),
|
||||
status: "constraint violation",
|
||||
status: constraintViolationStatus,
|
||||
})
|
||||
}
|
||||
|
||||
if st.workingSet.MergeActive() {
|
||||
ms := st.workingSet.MergeState()
|
||||
if ws.MergeActive() {
|
||||
ms := ws.MergeState()
|
||||
for _, tbl := range ms.TablesWithSchemaConflicts() {
|
||||
rows = append(rows, statusTableRow{
|
||||
tableName: tbl.String(),
|
||||
isStaged: byte(0),
|
||||
status: "schema conflict",
|
||||
status: schemaConflictStatus,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -195,7 +201,7 @@ func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) {
|
||||
|
||||
cnfTables, err := doltdb.TablesWithDataConflicts(ctx, roots.Working)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, tbl := range cnfTables {
|
||||
rows = append(rows, statusTableRow{
|
||||
@@ -218,6 +224,7 @@ func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) {
|
||||
status: statusString(td),
|
||||
})
|
||||
}
|
||||
|
||||
for _, td := range unstagedTables {
|
||||
tblName := tableName(td)
|
||||
if doltdb.IsFullTextTable(tblName) {
|
||||
@@ -249,6 +256,20 @@ func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) {
|
||||
})
|
||||
}
|
||||
|
||||
return rows, unstagedTables, nil
|
||||
}
|
||||
|
||||
func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) {
|
||||
// If no roots provider was set, then there is no status to report
|
||||
if st.rootsProvider == nil {
|
||||
return &StatusItr{rows: nil}, nil
|
||||
}
|
||||
|
||||
rows, _, err := getStatusRowsData(ctx, st.rootsProvider, st.workingSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &StatusItr{rows: rows}, nil
|
||||
}
|
||||
|
||||
@@ -272,7 +293,7 @@ func tableName(td diff.TableDelta) string {
|
||||
|
||||
func statusString(td diff.TableDelta) string {
|
||||
if td.IsAdd() {
|
||||
return "new table"
|
||||
return newTableStatus
|
||||
} else if td.IsDrop() {
|
||||
return "deleted"
|
||||
} else if td.IsRename() {
|
||||
@@ -284,6 +305,9 @@ func statusString(td diff.TableDelta) string {
|
||||
|
||||
const mergeConflictStatus = "conflict"
|
||||
const mergedStatus = "merged"
|
||||
const schemaConflictStatus = "schema conflict"
|
||||
const constraintViolationStatus = "constraint violation"
|
||||
const newTableStatus = "new table"
|
||||
|
||||
// Next retrieves the next row. It will return io.EOF if it's the last row.
|
||||
// After retrieving the last row, Close will be automatically closed.
|
||||
|
||||
@@ -759,6 +759,157 @@ var DoltScripts = []queries.ScriptTest{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dolt_status_ignored basic tests",
|
||||
SetUpScript: []string{
|
||||
"CREATE TABLE t (pk int primary key);",
|
||||
"INSERT INTO dolt_ignore VALUES ('ignored_*', true);",
|
||||
"CREATE TABLE ignored_test (pk int primary key);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
// Verify schema has 4 columns
|
||||
Query: "DESCRIBE dolt_status_ignored;",
|
||||
Expected: []sql.Row{
|
||||
{"table_name", "text", "NO", "PRI", nil, ""},
|
||||
{"staged", "tinyint(1)", "NO", "PRI", nil, ""},
|
||||
{"status", "text", "NO", "PRI", nil, ""},
|
||||
{"ignored", "tinyint(1)", "NO", "", nil, ""},
|
||||
},
|
||||
},
|
||||
{
|
||||
// Non-ignored unstaged table has ignored=false
|
||||
Query: "SELECT table_name, staged, status, ignored FROM dolt_status_ignored WHERE table_name = 't';",
|
||||
Expected: []sql.Row{{"t", byte(0), "new table", false}},
|
||||
},
|
||||
{
|
||||
// Ignored unstaged table has ignored=true
|
||||
Query: "SELECT table_name, staged, status, ignored FROM dolt_status_ignored WHERE table_name = 'ignored_test';",
|
||||
Expected: []sql.Row{{"ignored_test", byte(0), "new table", true}},
|
||||
},
|
||||
{
|
||||
// dolt_ignore table itself shows as not ignored
|
||||
Query: "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'dolt_ignore';",
|
||||
Expected: []sql.Row{{"dolt_ignore", false}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dolt_status_ignored staged tables always have ignored=0",
|
||||
SetUpScript: []string{
|
||||
// Create and stage table BEFORE adding ignore pattern
|
||||
"CREATE TABLE staged_test (pk int primary key);",
|
||||
"CALL DOLT_ADD('staged_test');",
|
||||
// Now add pattern that matches the already-staged table name
|
||||
"INSERT INTO dolt_ignore VALUES ('staged_*', true);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
// Staged table has ignored=false even if name matches ignore pattern
|
||||
Query: "SELECT table_name, staged, ignored FROM dolt_status_ignored WHERE table_name = 'staged_test';",
|
||||
Expected: []sql.Row{{"staged_test", byte(1), false}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dolt_status_ignored with AS OF and branch queries",
|
||||
SetUpScript: []string{
|
||||
"CALL DOLT_COMMIT('--allow-empty', '-m', 'empty commit');",
|
||||
"SET @commit1 = HASHOF('HEAD');",
|
||||
"CALL DOLT_TAG('tag1');",
|
||||
"CALL DOLT_CHECKOUT('-b', 'branch1');",
|
||||
"CREATE TABLE abc (pk int);",
|
||||
"CALL DOLT_ADD('abc');",
|
||||
"CALL DOLT_CHECKOUT('main');",
|
||||
"CREATE TABLE t (pk int primary key);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "SELECT table_name, staged, status, ignored FROM dolt_status_ignored;",
|
||||
Expected: []sql.Row{{"t", byte(0), "new table", false}},
|
||||
},
|
||||
{
|
||||
Query: "SELECT * FROM dolt_status_ignored AS OF 'tag1';",
|
||||
Expected: []sql.Row{},
|
||||
},
|
||||
{
|
||||
Query: "SELECT * FROM dolt_status_ignored AS OF @commit1;",
|
||||
Expected: []sql.Row{},
|
||||
},
|
||||
{
|
||||
Query: "SELECT table_name, staged, status, ignored FROM dolt_status_ignored AS OF 'branch1';",
|
||||
Expected: []sql.Row{{"abc", byte(1), "new table", false}},
|
||||
},
|
||||
{
|
||||
Query: "SELECT table_name, staged, status, ignored FROM `mydb/branch1`.dolt_status_ignored;",
|
||||
Expected: []sql.Row{{"abc", byte(1), "new table", false}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dolt_status_ignored with multiple ignore patterns",
|
||||
SetUpScript: []string{
|
||||
"INSERT INTO dolt_ignore VALUES ('temp_*', true);",
|
||||
"INSERT INTO dolt_ignore VALUES ('*_backup', true);",
|
||||
"CREATE TABLE temp_data (pk int primary key);",
|
||||
"CREATE TABLE users_backup (pk int primary key);",
|
||||
"CREATE TABLE normal_table (pk int primary key);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'temp_data';",
|
||||
Expected: []sql.Row{{"temp_data", true}},
|
||||
},
|
||||
{
|
||||
Query: "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'users_backup';",
|
||||
Expected: []sql.Row{{"users_backup", true}},
|
||||
},
|
||||
{
|
||||
Query: "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'normal_table';",
|
||||
Expected: []sql.Row{{"normal_table", false}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dolt_status_ignored with empty dolt_ignore",
|
||||
SetUpScript: []string{
|
||||
"CREATE TABLE t1 (pk int primary key);",
|
||||
"CREATE TABLE t2 (pk int primary key);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
// With no ignore patterns, all tables should have ignored=false
|
||||
Query: "SELECT table_name, ignored FROM dolt_status_ignored ORDER BY table_name;",
|
||||
Expected: []sql.Row{
|
||||
{"t1", false},
|
||||
{"t2", false},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dolt_status_ignored with conflicting patterns",
|
||||
SetUpScript: []string{
|
||||
// First pattern ignores tables starting with "test_"
|
||||
"INSERT INTO dolt_ignore VALUES ('test_*', true);",
|
||||
// Second pattern un-ignores specific table
|
||||
"INSERT INTO dolt_ignore VALUES ('test_special', false);",
|
||||
"CREATE TABLE test_normal (pk int primary key);",
|
||||
"CREATE TABLE test_special (pk int primary key);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
// test_normal matches ignore pattern
|
||||
Query: "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'test_normal';",
|
||||
Expected: []sql.Row{{"test_normal", true}},
|
||||
},
|
||||
{
|
||||
// test_special is explicitly not ignored (false overrides wildcard)
|
||||
Query: "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'test_special';",
|
||||
Expected: []sql.Row{{"test_special", false}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dolt_hashof_table tests",
|
||||
SetUpScript: []string{
|
||||
@@ -8670,6 +8821,7 @@ var DoltSystemVariables = []queries.ScriptTest{
|
||||
{"dolt_remotes"},
|
||||
{"dolt_stashes"},
|
||||
{"dolt_status"},
|
||||
{"dolt_status_ignored"},
|
||||
{"dolt_workspace_test"},
|
||||
{"test"},
|
||||
},
|
||||
|
||||
@@ -60,9 +60,10 @@ teardown() {
|
||||
@test "ls: --system shows system tables" {
|
||||
run dolt ls --system
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 26 ]
|
||||
[ "${#lines[@]}" -eq 27 ]
|
||||
[[ "$output" =~ "System tables:" ]] || false
|
||||
[[ "$output" =~ "dolt_status" ]] || false
|
||||
[[ "$output" =~ "dolt_status_ignored" ]] || false
|
||||
[[ "$output" =~ "dolt_commits" ]] || false
|
||||
[[ "$output" =~ "dolt_commit_ancestors" ]] || false
|
||||
[[ "$output" =~ "dolt_constraint_violations" ]] || false
|
||||
|
||||
@@ -1165,3 +1165,70 @@ SQL
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "dolt_conflict_id" ]] || false
|
||||
}
|
||||
|
||||
@test "system-tables: query dolt_status_ignored system table" {
|
||||
# Create a table and add it
|
||||
dolt sql -q "CREATE TABLE test (pk INT PRIMARY KEY, c1 INT)"
|
||||
dolt add test
|
||||
dolt commit -m "Added test table"
|
||||
|
||||
# Create an ignored table pattern
|
||||
dolt sql -q "INSERT INTO dolt_ignore VALUES ('ignored_*', true)"
|
||||
|
||||
# Create a table that matches the ignore pattern
|
||||
dolt sql -q "CREATE TABLE ignored_table (pk INT PRIMARY KEY)"
|
||||
|
||||
# Create a non-ignored table with changes
|
||||
dolt sql -q "INSERT INTO test VALUES (1, 1)"
|
||||
|
||||
# Query dolt_status - shows all tables (does not filter ignored)
|
||||
run dolt sql -q "SELECT table_name FROM dolt_status WHERE staged = false"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test" ]] || false
|
||||
[[ "$output" =~ "ignored_table" ]] || false
|
||||
|
||||
# Query dolt_status_ignored - shows all tables with ignored column
|
||||
run dolt sql -q "SELECT table_name, ignored FROM dolt_status_ignored WHERE staged = false ORDER BY table_name"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "ignored_table" ]] || false
|
||||
[[ "$output" =~ "test" ]] || false
|
||||
|
||||
# Verify ignored column correctly identifies ignored tables
|
||||
run dolt sql -r csv -q "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'ignored_table'"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "ignored_table,true" ]] || false
|
||||
|
||||
# Verify non-ignored table has ignored = false
|
||||
run dolt sql -r csv -q "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'test'"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test,false" ]] || false
|
||||
|
||||
# Verify schema has 4 columns
|
||||
run dolt sql -q "DESCRIBE dolt_status_ignored"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "table_name" ]] || false
|
||||
[[ "$output" =~ "staged" ]] || false
|
||||
[[ "$output" =~ "status" ]] || false
|
||||
[[ "$output" =~ "ignored" ]] || false
|
||||
}
|
||||
|
||||
@test "system-tables: dolt_status_ignored shows staged tables without ignored flag" {
|
||||
# Create and stage a table
|
||||
dolt sql -q "CREATE TABLE staged_test (pk INT PRIMARY KEY)"
|
||||
dolt add staged_test
|
||||
|
||||
# Query staged tables - should have ignored = false
|
||||
run dolt sql -q "SELECT table_name, ignored FROM dolt_status_ignored WHERE staged = true AND table_name = 'staged_test'"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "staged_test" ]] || false
|
||||
# Staged tables should never be marked as ignored
|
||||
run dolt sql -r csv -q "SELECT ignored FROM dolt_status_ignored WHERE staged = true AND table_name = 'staged_test'"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "false" ]] || false
|
||||
}
|
||||
|
||||
@test "system-tables: dolt_status_ignored shows in dolt ls --system" {
|
||||
run dolt ls --system
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "dolt_status_ignored" ]] || false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user