From 00f459df84c9934ee040bf5e2c75ea3c1bcb8a73 Mon Sep 17 00:00:00 2001 From: David Dansby <39511285+codeaucafe@users.noreply.github.com> Date: Wed, 17 Dec 2025 23:12:56 -0800 Subject: [PATCH 1/6] feat(sqle): add dolt_status_ignored system table Add new dolt_status_ignored system table that extends dolt_status with an "ignored" column to show which unstaged tables match dolt_ignore patterns. This provides SQL equivalent of dolt status --ignored functionality. Implementation includes: - StatusIgnoredTable type with schema containing table_name, staged, status, and ignored columns - Registration in system table constants and generated table names lists - Helper function getStatusTableRootsProvider to eliminate duplicate switch case logic between StatusTableName and StatusIgnoredTableName in database.go - Shared getStatusRowsData function used by both dolt_status and dolt_status_ignored to collect status data from roots and working set - Unexported helper functions in status_ignored_table.go for ignore pattern checking: getIgnorePatterns, buildUnstagedTableNameSet, and checkIfIgnored - bats integration tests verifying behavior The ignored column is only set for unstaged tables that match patterns in dolt_ignore. Staged tables, constraint violations, merge conflicts, and schema conflicts always have ignored = 0. Refs: #5862 --- go/libraries/doltcore/doltdb/system_table.go | 5 + go/libraries/doltcore/sqle/database.go | 123 ++++++----- .../sqle/dtables/status_ignored_table.go | 196 ++++++++++++++++++ .../doltcore/sqle/dtables/status_table.go | 83 ++++++-- integration-tests/bats/system-tables.bats | 67 ++++++ 5 files changed, 404 insertions(+), 70 deletions(-) create mode 100644 go/libraries/doltcore/sqle/dtables/status_ignored_table.go diff --git a/go/libraries/doltcore/doltdb/system_table.go b/go/libraries/doltcore/doltdb/system_table.go index 9701487a00..3ac76c9e34 100644 --- a/go/libraries/doltcore/doltdb/system_table.go +++ b/go/libraries/doltcore/doltdb/system_table.go @@ -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, } diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index 170cd2dbbf..1113c73f19 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -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. diff --git a/go/libraries/doltcore/sqle/dtables/status_ignored_table.go b/go/libraries/doltcore/sqle/dtables/status_ignored_table.go new file mode 100644 index 0000000000..3eda665608 --- /dev/null +++ b/go/libraries/doltcore/sqle/dtables/status_ignored_table.go @@ -0,0 +1,196 @@ +// Copyright 2020 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/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. +func NewStatusIgnoredTable(_ *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 byte +} + +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 := byte(0) + // Only check ignore patterns for unstaged tables + if row.isStaged == byte(0) && unstagedTableNames[row.tableName] { + ignored = checkIfIgnored(row.tableName, ignorePatterns) + } + 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 +} + +// checkIfIgnored returns 1 if the table name matches an ignore pattern, 0 otherwise. +func checkIfIgnored(tableName string, ignorePatterns doltdb.IgnorePatterns) byte { + tblNameObj := doltdb.TableName{Name: tableName} + result, err := ignorePatterns.IsTableNameIgnored(tblNameObj) + if err != nil { + return byte(0) + } + if result == doltdb.Ignore { + return byte(1) + } + return byte(0) +} + +// 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 +} diff --git a/go/libraries/doltcore/sqle/dtables/status_table.go b/go/libraries/doltcore/sqle/dtables/status_table.go index 8213544981..2158d173c3 100644 --- a/go/libraries/doltcore/sqle/dtables/status_table.go +++ b/go/libraries/doltcore/sqle/dtables/status_table.go @@ -115,6 +115,14 @@ type statusTableRow struct { // of this table when you are using local vs remote sql connections. } +// statusRowData contains the data for a single status row. +type statusRowData struct { + tableName string + status string + isStaged byte +} + +// 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 +132,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, +) ([]statusRowData, []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 +160,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,35 +170,35 @@ 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)) + rows := make([]statusRowData, 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{ + rows = append(rows, statusRowData{ tableName: tbl.String(), status: "constraint violation", }) } - if st.workingSet.MergeActive() { - ms := st.workingSet.MergeState() + if ws.MergeActive() { + ms := ws.MergeState() for _, tbl := range ms.TablesWithSchemaConflicts() { - rows = append(rows, statusTableRow{ + rows = append(rows, statusRowData{ tableName: tbl.String(), isStaged: byte(0), - status: "schema conflict", + status: mergedStatus, }) } for _, tbl := range ms.MergedTables() { - rows = append(rows, statusTableRow{ + rows = append(rows, statusRowData{ tableName: tbl.String(), isStaged: byte(1), status: mergedStatus, @@ -195,10 +208,10 @@ 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{ + rows = append(rows, statusRowData{ tableName: tbl.String(), status: mergeConflictStatus, }) @@ -212,12 +225,13 @@ func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) { if containsTableName(tblName, cvTables) { continue } - rows = append(rows, statusTableRow{ + rows = append(rows, statusRowData{ tableName: tblName, isStaged: byte(1), status: statusString(td), }) } + for _, td := range unstagedTables { tblName := tableName(td) if doltdb.IsFullTextTable(tblName) { @@ -226,7 +240,7 @@ func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) { if containsTableName(tblName, cvTables) { continue } - rows = append(rows, statusTableRow{ + rows = append(rows, statusRowData{ tableName: tblName, isStaged: byte(0), status: statusString(td), @@ -234,7 +248,7 @@ func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) { } for _, sd := range stagedSchemas { - rows = append(rows, statusTableRow{ + rows = append(rows, statusRowData{ tableName: sd.CurName(), isStaged: byte(1), status: schemaStatusString(sd), @@ -242,13 +256,38 @@ func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) { } for _, sd := range unstagedSchemas { - rows = append(rows, statusTableRow{ + rows = append(rows, statusRowData{ tableName: sd.CurName(), isStaged: byte(0), status: schemaStatusString(sd), }) } + 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 + } + + // Get status data using the shared function + statusRows, _, err := getStatusRowsData(ctx, st.rootsProvider, st.workingSet) + if err != nil { + return nil, err + } + + // Convert statusRowData to statusTableRow + rows := make([]statusTableRow, len(statusRows)) + for i, row := range statusRows { + rows[i] = statusTableRow{ + tableName: row.tableName, + isStaged: row.isStaged, + status: row.status, + } + } + return &StatusItr{rows: rows}, nil } diff --git a/integration-tests/bats/system-tables.bats b/integration-tests/bats/system-tables.bats index f6546fbb93..622013cb97 100644 --- a/integration-tests/bats/system-tables.bats +++ b/integration-tests/bats/system-tables.bats @@ -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,1" ]] || false + + # Verify non-ignored table has ignored = 0 + run dolt sql -r csv -q "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'test'" + [ "$status" -eq 0 ] + [[ "$output" =~ "test,0" ]] || 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" =~ "0" ]] || false +} + +@test "system-tables: dolt_status_ignored shows in dolt ls --system" { + run dolt ls --system + [ "$status" -eq 0 ] + [[ "$output" =~ "dolt_status_ignored" ]] || false +} From 33a13363a2d4c91cbf83d8edd6bde577617139a0 Mon Sep 17 00:00:00 2001 From: David Dansby <39511285+codeaucafe@users.noreply.github.com> Date: Thu, 18 Dec 2025 22:28:30 -0800 Subject: [PATCH 2/6] fix(sqle): fix status table bugs and refactor redundant row struct Fix bugs introduced in initial dolt_status_ignored implementation commit and refactor to eliminate duplicate code between status tables. fixes: - Fix schema conflict status incorrectly set to "merged" instead of "schema conflict" in getStatusRowsData - Add dolt_status_ignored to expected system tables list in DOLT_SHOW_SYSTEM_TABLES test (should fix existing test failures) Refs: #5862 --- .../doltcore/sqle/dtables/status_table.go | 42 ++++++------------- .../doltcore/sqle/enginetest/dolt_queries.go | 1 + 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/go/libraries/doltcore/sqle/dtables/status_table.go b/go/libraries/doltcore/sqle/dtables/status_table.go index 2158d173c3..5c303c9d20 100644 --- a/go/libraries/doltcore/sqle/dtables/status_table.go +++ b/go/libraries/doltcore/sqle/dtables/status_table.go @@ -115,13 +115,6 @@ type statusTableRow struct { // of this table when you are using local vs remote sql connections. } -// statusRowData contains the data for a single status row. -type statusRowData struct { - tableName string - status string - isStaged byte -} - // 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 { @@ -139,7 +132,7 @@ func getStatusRowsData( ctx *sql.Context, rp env.RootsProvider[*sql.Context], ws *doltdb.WorkingSet, -) ([]statusRowData, []diff.TableDelta, error) { +) ([]statusTableRow, []diff.TableDelta, error) { if rp == nil { return nil, nil, nil } @@ -173,7 +166,7 @@ func getStatusRowsData( return nil, nil, err } - rows := make([]statusRowData, 0, len(stagedTables)+len(unstagedTables)+len(stagedSchemas)+len(unstagedSchemas)) + rows := make([]statusTableRow, 0, len(stagedTables)+len(unstagedTables)+len(stagedSchemas)+len(unstagedSchemas)) cvTables, err := doltdb.TablesWithConstraintViolations(ctx, roots.Working) if err != nil { @@ -181,7 +174,7 @@ func getStatusRowsData( } for _, tbl := range cvTables { - rows = append(rows, statusRowData{ + rows = append(rows, statusTableRow{ tableName: tbl.String(), status: "constraint violation", }) @@ -190,15 +183,15 @@ func getStatusRowsData( if ws.MergeActive() { ms := ws.MergeState() for _, tbl := range ms.TablesWithSchemaConflicts() { - rows = append(rows, statusRowData{ + rows = append(rows, statusTableRow{ tableName: tbl.String(), isStaged: byte(0), - status: mergedStatus, + status: "schema conflict", }) } for _, tbl := range ms.MergedTables() { - rows = append(rows, statusRowData{ + rows = append(rows, statusTableRow{ tableName: tbl.String(), isStaged: byte(1), status: mergedStatus, @@ -211,7 +204,7 @@ func getStatusRowsData( return nil, nil, err } for _, tbl := range cnfTables { - rows = append(rows, statusRowData{ + rows = append(rows, statusTableRow{ tableName: tbl.String(), status: mergeConflictStatus, }) @@ -225,7 +218,7 @@ func getStatusRowsData( if containsTableName(tblName, cvTables) { continue } - rows = append(rows, statusRowData{ + rows = append(rows, statusTableRow{ tableName: tblName, isStaged: byte(1), status: statusString(td), @@ -240,7 +233,7 @@ func getStatusRowsData( if containsTableName(tblName, cvTables) { continue } - rows = append(rows, statusRowData{ + rows = append(rows, statusTableRow{ tableName: tblName, isStaged: byte(0), status: statusString(td), @@ -248,7 +241,7 @@ func getStatusRowsData( } for _, sd := range stagedSchemas { - rows = append(rows, statusRowData{ + rows = append(rows, statusTableRow{ tableName: sd.CurName(), isStaged: byte(1), status: schemaStatusString(sd), @@ -256,7 +249,7 @@ func getStatusRowsData( } for _, sd := range unstagedSchemas { - rows = append(rows, statusRowData{ + rows = append(rows, statusTableRow{ tableName: sd.CurName(), isStaged: byte(0), status: schemaStatusString(sd), @@ -272,22 +265,11 @@ func newStatusItr(ctx *sql.Context, st *StatusTable) (*StatusItr, error) { return &StatusItr{rows: nil}, nil } - // Get status data using the shared function - statusRows, _, err := getStatusRowsData(ctx, st.rootsProvider, st.workingSet) + rows, _, err := getStatusRowsData(ctx, st.rootsProvider, st.workingSet) if err != nil { return nil, err } - // Convert statusRowData to statusTableRow - rows := make([]statusTableRow, len(statusRows)) - for i, row := range statusRows { - rows[i] = statusTableRow{ - tableName: row.tableName, - isStaged: row.isStaged, - status: row.status, - } - } - return &StatusItr{rows: rows}, nil } diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go index 8fcd279daa..911a42008a 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go @@ -8670,6 +8670,7 @@ var DoltSystemVariables = []queries.ScriptTest{ {"dolt_remotes"}, {"dolt_stashes"}, {"dolt_status"}, + {"dolt_status_ignored"}, {"dolt_workspace_test"}, {"test"}, }, From a3c7660df15d3922403a0af71e01fe93b83161dc Mon Sep 17 00:00:00 2001 From: David Dansby <39511285+codeaucafe@users.noreply.github.com> Date: Fri, 19 Dec 2025 01:19:40 -0800 Subject: [PATCH 3/6] fix(sqle): address PR feedback for dolt_status_ignored; fix & add tests Address PR review feedback for dolt_status_ignored implementation with refactors to error handling, adapter pattern, test coverage, and copyright year. Changes: - Fix copyright year from 2020 to 2025 in status_ignored_table.go - Add adapter pattern to NewStatusIgnoredTable; matches StatusTable implementation. - Add NewStatusIgnoredTableWithNoAdapter for default behavior - Fix error handling in checkIfIgnored to return errors instead of silently returning byte(0) - Propagate ignore pattern errors up the call stack Test coverage additions: - Empty dolt_ignore table test verifying all tables show ignored=0 - Conflicting patterns test with wildcard (test_*=true) vs specific override (test_special=false) - Update ls.bats to expect 27 system tables instead of 26 Error handling refactored to now matches patterns in status.go, commit .go, and diff.go where IsTableNameIgnored errors are properly propagated up rather than swallowed. Refs: #5862 --- .../sqle/dtables/status_ignored_table.go | 32 +++- .../doltcore/sqle/enginetest/dolt_queries.go | 151 ++++++++++++++++++ integration-tests/bats/ls.bats | 3 +- 3 files changed, 177 insertions(+), 9 deletions(-) diff --git a/go/libraries/doltcore/sqle/dtables/status_ignored_table.go b/go/libraries/doltcore/sqle/dtables/status_ignored_table.go index 3eda665608..085ab1c025 100644 --- a/go/libraries/doltcore/sqle/dtables/status_ignored_table.go +++ b/go/libraries/doltcore/sqle/dtables/status_ignored_table.go @@ -1,4 +1,4 @@ -// Copyright 2020 Dolthub, Inc. +// 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. @@ -24,6 +24,7 @@ import ( "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" ) @@ -82,8 +83,19 @@ func (st StatusIgnoredTable) PartitionRows(context *sql.Context, _ sql.Partition return newStatusIgnoredItr(context, &st) } -// NewStatusIgnoredTable creates a new StatusIgnoredTable. -func NewStatusIgnoredTable(_ *sql.Context, tableName string, ddb *doltdb.DoltDB, ws *doltdb.WorkingSet, rp env.RootsProvider[*sql.Context]) sql.Table { +// 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, @@ -131,7 +143,11 @@ func newStatusIgnoredItr(ctx *sql.Context, st *StatusIgnoredTable) (*StatusIgnor ignored := byte(0) // Only check ignore patterns for unstaged tables if row.isStaged == byte(0) && unstagedTableNames[row.tableName] { - ignored = checkIfIgnored(row.tableName, ignorePatterns) + var err error + ignored, err = checkIfIgnored(row.tableName, ignorePatterns) + if err != nil { + return nil, err + } } rows[i] = statusIgnoredTableRow{ tableName: row.tableName, @@ -168,16 +184,16 @@ func buildUnstagedTableNameSet(unstagedTables []diff.TableDelta) map[string]bool } // checkIfIgnored returns 1 if the table name matches an ignore pattern, 0 otherwise. -func checkIfIgnored(tableName string, ignorePatterns doltdb.IgnorePatterns) byte { +func checkIfIgnored(tableName string, ignorePatterns doltdb.IgnorePatterns) (byte, error) { tblNameObj := doltdb.TableName{Name: tableName} result, err := ignorePatterns.IsTableNameIgnored(tblNameObj) if err != nil { - return byte(0) + return byte(0), err } if result == doltdb.Ignore { - return byte(1) + return byte(1), nil } - return byte(0) + return byte(0), nil } // Next retrieves the next row. It will return io.EOF if it's the last row. diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go index 911a42008a..a3206e9cb5 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go @@ -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=0 + Query: "SELECT table_name, staged, status, ignored FROM dolt_status_ignored WHERE table_name = 't';", + Expected: []sql.Row{{"t", byte(0), "new table", byte(0)}}, + }, + { + // Ignored unstaged table has ignored=1 + 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", byte(1)}}, + }, + { + // 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", byte(0)}}, + }, + }, + }, + { + 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=0 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), byte(0)}}, + }, + }, + }, + { + 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", byte(0)}}, + }, + { + 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", byte(0)}}, + }, + { + Query: "SELECT table_name, staged, status, ignored FROM `mydb/branch1`.dolt_status_ignored;", + Expected: []sql.Row{{"abc", byte(1), "new table", byte(0)}}, + }, + }, + }, + { + 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", byte(1)}}, + }, + { + Query: "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'users_backup';", + Expected: []sql.Row{{"users_backup", byte(1)}}, + }, + { + Query: "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'normal_table';", + Expected: []sql.Row{{"normal_table", byte(0)}}, + }, + }, + }, + { + 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=0 + Query: "SELECT table_name, ignored FROM dolt_status_ignored ORDER BY table_name;", + Expected: []sql.Row{ + {"t1", byte(0)}, + {"t2", byte(0)}, + }, + }, + }, + }, + { + 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", byte(1)}}, + }, + { + // 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", byte(0)}}, + }, + }, + }, { Name: "dolt_hashof_table tests", SetUpScript: []string{ diff --git a/integration-tests/bats/ls.bats b/integration-tests/bats/ls.bats index fbea364d1a..6e1abe3abd 100755 --- a/integration-tests/bats/ls.bats +++ b/integration-tests/bats/ls.bats @@ -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 From 3186b4d03ffbb5b5b48fb243b99cb5732e0279db Mon Sep 17 00:00:00 2001 From: David Dansby <39511285+codeaucafe@users.noreply.github.com> Date: Thu, 8 Jan 2026 18:30:51 -0800 Subject: [PATCH 4/6] fix(sqle): limit ignore check to new tables and add status constants Refactor dolt_status_ignored to match Git ignore behavior and improve code quality. Logic fix: - Only check ignore patterns for tables with "new table" status Code improvements: - Add constants for status strings (schemaConflictStatus, constraintViolationStatus, newTableStatus) to match existing pattern used by mergeConflictStatus and mergedStatus - Inline checkIfIgnored function since it was only called once - Change ignored field from byte to bool in statusIgnoredTableRow since wire protocol workaround only applies to statusTableRow Refs: #5862 --- .../sqle/dtables/status_ignored_table.go | 32 +++++++------------ .../doltcore/sqle/dtables/status_table.go | 9 ++++-- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/go/libraries/doltcore/sqle/dtables/status_ignored_table.go b/go/libraries/doltcore/sqle/dtables/status_ignored_table.go index 085ab1c025..402df8d980 100644 --- a/go/libraries/doltcore/sqle/dtables/status_ignored_table.go +++ b/go/libraries/doltcore/sqle/dtables/status_ignored_table.go @@ -1,4 +1,4 @@ -// Copyright 2025 Dolthub, Inc. +// 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. @@ -113,7 +113,7 @@ type statusIgnoredTableRow struct { tableName string status string isStaged byte // not a bool bc wire protocol confuses bools and tinyint(1) - ignored byte + ignored bool } func newStatusIgnoredItr(ctx *sql.Context, st *StatusIgnoredTable) (*StatusIgnoredItr, error) { @@ -140,14 +140,19 @@ func newStatusIgnoredItr(ctx *sql.Context, st *StatusIgnoredTable) (*StatusIgnor // Convert status rows to status_ignored rows, adding the ignored column rows := make([]statusIgnoredTableRow, len(statusRows)) for i, row := range statusRows { - ignored := byte(0) - // Only check ignore patterns for unstaged tables - if row.isStaged == byte(0) && unstagedTableNames[row.tableName] { - var err error - ignored, err = checkIfIgnored(row.tableName, ignorePatterns) + 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, @@ -183,19 +188,6 @@ func buildUnstagedTableNameSet(unstagedTables []diff.TableDelta) map[string]bool return result } -// checkIfIgnored returns 1 if the table name matches an ignore pattern, 0 otherwise. -func checkIfIgnored(tableName string, ignorePatterns doltdb.IgnorePatterns) (byte, error) { - tblNameObj := doltdb.TableName{Name: tableName} - result, err := ignorePatterns.IsTableNameIgnored(tblNameObj) - if err != nil { - return byte(0), err - } - if result == doltdb.Ignore { - return byte(1), nil - } - return byte(0), nil -} - // 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 { diff --git a/go/libraries/doltcore/sqle/dtables/status_table.go b/go/libraries/doltcore/sqle/dtables/status_table.go index 5c303c9d20..de325486a3 100644 --- a/go/libraries/doltcore/sqle/dtables/status_table.go +++ b/go/libraries/doltcore/sqle/dtables/status_table.go @@ -176,7 +176,7 @@ func getStatusRowsData( for _, tbl := range cvTables { rows = append(rows, statusTableRow{ tableName: tbl.String(), - status: "constraint violation", + status: constraintViolationStatus, }) } @@ -186,7 +186,7 @@ func getStatusRowsData( rows = append(rows, statusTableRow{ tableName: tbl.String(), isStaged: byte(0), - status: "schema conflict", + status: schemaConflictStatus, }) } @@ -293,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() { @@ -305,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. From a94e5bee1286a783c21b76decd0731fbc4e24100 Mon Sep 17 00:00:00 2001 From: David Dansby <39511285+codeaucafe@users.noreply.github.com> Date: Thu, 8 Jan 2026 21:19:15 -0800 Subject: [PATCH 5/6] fix(sqle): update tests to use bool type for ignored column Update test assertions in dolt_status_ignored tests to use boolean values (true/false) instead of byte values (byte(0)/byte(1)) for the ignored column in statusIgnoredTableRow. Refs: #5862 --- .../doltcore/sqle/enginetest/dolt_queries.go | 36 +++++++++---------- integration-tests/bats/system-tables.bats | 6 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go index a3206e9cb5..f0436f4a79 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go @@ -778,19 +778,19 @@ var DoltScripts = []queries.ScriptTest{ }, }, { - // Non-ignored unstaged table has ignored=0 + // 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", byte(0)}}, + Expected: []sql.Row{{"t", byte(0), "new table", false}}, }, { - // Ignored unstaged table has ignored=1 + // 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", byte(1)}}, + 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", byte(0)}}, + Expected: []sql.Row{{"dolt_ignore", false}}, }, }, }, @@ -805,9 +805,9 @@ var DoltScripts = []queries.ScriptTest{ }, Assertions: []queries.ScriptTestAssertion{ { - // Staged table has ignored=0 even if name matches ignore pattern + // 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), byte(0)}}, + Expected: []sql.Row{{"staged_test", byte(1), false}}, }, }, }, @@ -826,7 +826,7 @@ var DoltScripts = []queries.ScriptTest{ Assertions: []queries.ScriptTestAssertion{ { Query: "SELECT table_name, staged, status, ignored FROM dolt_status_ignored;", - Expected: []sql.Row{{"t", byte(0), "new table", byte(0)}}, + Expected: []sql.Row{{"t", byte(0), "new table", false}}, }, { Query: "SELECT * FROM dolt_status_ignored AS OF 'tag1';", @@ -838,11 +838,11 @@ var DoltScripts = []queries.ScriptTest{ }, { Query: "SELECT table_name, staged, status, ignored FROM dolt_status_ignored AS OF 'branch1';", - Expected: []sql.Row{{"abc", byte(1), "new table", byte(0)}}, + 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", byte(0)}}, + Expected: []sql.Row{{"abc", byte(1), "new table", false}}, }, }, }, @@ -858,15 +858,15 @@ var DoltScripts = []queries.ScriptTest{ Assertions: []queries.ScriptTestAssertion{ { Query: "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'temp_data';", - Expected: []sql.Row{{"temp_data", byte(1)}}, + 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", byte(1)}}, + 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", byte(0)}}, + Expected: []sql.Row{{"normal_table", false}}, }, }, }, @@ -878,11 +878,11 @@ var DoltScripts = []queries.ScriptTest{ }, Assertions: []queries.ScriptTestAssertion{ { - // With no ignore patterns, all tables should have ignored=0 + // 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", byte(0)}, - {"t2", byte(0)}, + {"t1", false}, + {"t2", false}, }, }, }, @@ -901,12 +901,12 @@ var DoltScripts = []queries.ScriptTest{ { // test_normal matches ignore pattern Query: "SELECT table_name, ignored FROM dolt_status_ignored WHERE table_name = 'test_normal';", - Expected: []sql.Row{{"test_normal", byte(1)}}, + 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", byte(0)}}, + Expected: []sql.Row{{"test_special", false}}, }, }, }, diff --git a/integration-tests/bats/system-tables.bats b/integration-tests/bats/system-tables.bats index 622013cb97..a7224095f7 100644 --- a/integration-tests/bats/system-tables.bats +++ b/integration-tests/bats/system-tables.bats @@ -1196,12 +1196,12 @@ SQL # 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,1" ]] || false + [[ "$output" =~ "ignored_table,true" ]] || false - # Verify non-ignored table has ignored = 0 + # 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,0" ]] || false + [[ "$output" =~ "test,false" ]] || false # Verify schema has 4 columns run dolt sql -q "DESCRIBE dolt_status_ignored" From 6aaf56f2aaac26b591c31ca6dbb8c2874191a5cb Mon Sep 17 00:00:00 2001 From: David Dansby <39511285+codeaucafe@users.noreply.github.com> Date: Sun, 11 Jan 2026 17:16:51 -0800 Subject: [PATCH 6/6] test(bats): fix dolt_status_ignored bool assert Update test assert to check for "false" bool instead of int "0" for the ignored column. This is to align with change to use boolean type for the ignored column in the dolt_status_ignored system table. The other tests were previously fixed to handle this type change, but this one slipped through the cracks. Refs: #5862 --- integration-tests/bats/system-tables.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/bats/system-tables.bats b/integration-tests/bats/system-tables.bats index a7224095f7..64849b24e3 100644 --- a/integration-tests/bats/system-tables.bats +++ b/integration-tests/bats/system-tables.bats @@ -1224,7 +1224,7 @@ SQL # 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" =~ "0" ]] || false + [[ "$output" =~ "false" ]] || false } @test "system-tables: dolt_status_ignored shows in dolt ls --system" {