diff --git a/go/libraries/doltcore/diff/table_deltas.go b/go/libraries/doltcore/diff/table_deltas.go index 89c8a957704..93de7eff0e7 100644 --- a/go/libraries/doltcore/diff/table_deltas.go +++ b/go/libraries/doltcore/diff/table_deltas.go @@ -625,6 +625,21 @@ func (td TableDelta) GetRowData(ctx context.Context) (from, to durable.Index, er return from, to, nil } +// GetUniqueSchemaNamesFromTableNames returns a list of unique schema names from a list of table names +func GetUniqueSchemaNamesFromTableDeltas(deltas []TableDelta) []string { + schemaMap := make(map[string]struct{}) + var schemas []string + + for _, td := range deltas { + if _, exists := schemaMap[td.ToName.Schema]; !exists { + schemaMap[td.ToName.Schema] = struct{}{} + schemas = append(schemas, td.ToName.Schema) + } + } + + return schemas +} + // WorkingSetContainsOnlyIgnoredTables returns true if all changes in working set are ignored tables. // Otherwise, if there are any non-ignored changes, returns false. // Note that only unstaged tables are subject to dolt_ignore (this is consistent with what git does.) @@ -638,7 +653,8 @@ func WorkingSetContainsOnlyIgnoredTables(ctx context.Context, roots doltdb.Roots return false, nil } - ignorePatterns, err := doltdb.GetIgnoredTablePatterns(ctx, roots) + schemas := GetUniqueSchemaNamesFromTableDeltas(unstaged) + ignorePatternMap, err := doltdb.GetIgnoredTablePatterns(ctx, roots, schemas) if err != nil { return false, err } @@ -647,6 +663,8 @@ func WorkingSetContainsOnlyIgnoredTables(ctx context.Context, roots doltdb.Roots if !(tableDelta.IsAdd()) { return false, nil } + + ignorePatterns := ignorePatternMap[tableDelta.ToName.Schema] isIgnored, err := ignorePatterns.IsTableNameIgnored(tableDelta.ToName) if err != nil { return false, err diff --git a/go/libraries/doltcore/doltdb/ignore.go b/go/libraries/doltcore/doltdb/ignore.go index 7de764efe03..8e1904a0c9e 100644 --- a/go/libraries/doltcore/doltdb/ignore.go +++ b/go/libraries/doltcore/doltdb/ignore.go @@ -68,72 +68,82 @@ func convertTupleToIgnoreBoolean(valueDesc val.TupleDesc, valueTuple val.Tuple) return ignore, nil } -func GetIgnoredTablePatterns(ctx context.Context, roots Roots) (IgnorePatterns, error) { - var ignorePatterns []IgnorePattern +func GetIgnoredTablePatterns(ctx context.Context, roots Roots, schemas []string) (map[string]IgnorePatterns, error) { + ignorePatternsForSchemas := make(map[string]IgnorePatterns) workingSet := roots.Working - table, found, err := workingSet.GetTable(ctx, TableName{Name: IgnoreTableName}) - if err != nil { - return nil, err - } - if !found { - // dolt_ignore doesn't exist, so don't filter any tables. - return ignorePatterns, nil - } - index, err := table.GetRowData(ctx) - if table.Format() == types.Format_LD_1 { - // dolt_ignore is not supported for the legacy storage format. - return ignorePatterns, nil - } - if err != nil { - return nil, err - } - ignoreTableSchema, err := table.GetSchema(ctx) - if err != nil { - return nil, err - } - keyDesc, valueDesc := ignoreTableSchema.GetMapDescriptors() - if !keyDesc.Equals(val.NewTupleDescriptor(val.Type{Enc: val.StringEnc})) { - return nil, fmt.Errorf("dolt_ignore had unexpected key type, this should never happen") - } + for _, schemaName := range schemas { + var ignorePatterns []IgnorePattern - ignoreTableMap, err := durable.ProllyMapFromIndex(index).IterAll(ctx) - if err != nil { - return nil, err - } - for { - keyTuple, valueTuple, err := ignoreTableMap.Next(ctx) - if err == io.EOF { - break + tname := TableName{Name: IgnoreTableName, Schema: schemaName} + table, found, err := workingSet.GetTable(ctx, tname) + if err != nil { + return nil, err + } + if !found { + // dolt_ignore doesn't exist, so don't filter any tables. + continue + } + index, err := table.GetRowData(ctx) + if table.Format() == types.Format_LD_1 { + // dolt_ignore is not supported for the legacy storage format. + continue + } + if err != nil { + return nil, err } + ignoreTableSchema, err := table.GetSchema(ctx) if err != nil { return nil, err } + keyDesc, valueDesc := ignoreTableSchema.GetMapDescriptors() - pattern, ok := keyDesc.GetString(0, keyTuple) - if !ok { - return nil, fmt.Errorf("could not read pattern") + if !keyDesc.Equals(val.NewTupleDescriptor(val.Type{Enc: val.StringEnc})) { + return nil, fmt.Errorf("dolt_ignore had unexpected key type, this should never happen") } - ignore, err := ConvertTupleToIgnoreBoolean(valueDesc, valueTuple) + + ignoreTableMap, err := durable.ProllyMapFromIndex(index).IterAll(ctx) if err != nil { return nil, err } + for { + keyTuple, valueTuple, err := ignoreTableMap.Next(ctx) + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + + pattern, ok := keyDesc.GetString(0, keyTuple) + if !ok { + return nil, fmt.Errorf("could not read pattern") + } + ignore, err := ConvertTupleToIgnoreBoolean(valueDesc, valueTuple) + if err != nil { + return nil, err + } + ignorePatterns = append(ignorePatterns, NewIgnorePattern(pattern, ignore)) + } - ignorePatterns = append(ignorePatterns, NewIgnorePattern(pattern, ignore)) + ignorePatternsForSchemas[schemaName] = ignorePatterns } - return ignorePatterns, nil + + return ignorePatternsForSchemas, nil } // ExcludeIgnoredTables takes a list of table names and removes any tables that should be ignored, // as determined by the patterns in the dolt_ignore table. // The ignore patterns are read from the dolt_ignore table in the working set. func ExcludeIgnoredTables(ctx context.Context, roots Roots, tables []TableName) ([]TableName, error) { - ignorePatterns, err := GetIgnoredTablePatterns(ctx, roots) + schemas := GetUniqueSchemaNamesFromTableNames(tables) + ignorePatternMap, err := GetIgnoredTablePatterns(ctx, roots, schemas) if err != nil { return nil, err } filteredTables := []TableName{} for _, tbl := range tables { + ignorePatterns := ignorePatternMap[tbl.Schema] ignored, err := ignorePatterns.IsTableNameIgnored(tbl) if err != nil { return nil, err diff --git a/go/libraries/doltcore/doltdb/root_val.go b/go/libraries/doltcore/doltdb/root_val.go index f4f1b77ffef..d079e7651f8 100644 --- a/go/libraries/doltcore/doltdb/root_val.go +++ b/go/libraries/doltcore/doltdb/root_val.go @@ -835,6 +835,21 @@ func UnqualifiedTableNamesAsString(names []TableName) string { return sb.String() } +// GetUniqueSchemaNamesFromTableNames returns a list of unique schema names from a list of table names +func GetUniqueSchemaNamesFromTableNames(names []TableName) []string { + schemaMap := make(map[string]struct{}) + var schemas []string + + for _, t := range names { + if _, exists := schemaMap[t.Schema]; !exists { + schemaMap[t.Schema] = struct{}{} + schemas = append(schemas, t.Schema) + } + } + + return schemas +} + // DefaultSchemaName is the name of the default schema. Tables with this schema name will be stored in the // primary (unnamed) table store in a root. var DefaultSchemaName = "" @@ -1205,11 +1220,13 @@ func schemaNames(ctx context.Context, root RootValue) ([]string, error) { // FilterIgnoredTables takes a slice of table names and divides it into new slices based on whether the table is ignored, not ignored, or matches conflicting ignore patterns. func FilterIgnoredTables(ctx context.Context, tables []TableName, roots Roots) (ignoredTables IgnoredTables, err error) { - ignorePatterns, err := GetIgnoredTablePatterns(ctx, roots) + schemas := GetUniqueSchemaNamesFromTableNames(tables) + ignorePatternMap, err := GetIgnoredTablePatterns(ctx, roots, schemas) if err != nil { return ignoredTables, err } for _, tableName := range tables { + ignorePatterns := ignorePatternMap[tableName.Schema] ignored, err := ignorePatterns.IsTableNameIgnored(tableName) if conflict := AsDoltIgnoreInConflict(err); conflict != nil { ignoredTables.Conflicts = append(ignoredTables.Conflicts, *conflict) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index 4e69bbccfc6..e949a6b7f1f 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -636,15 +636,23 @@ func (db Database) getTableInsensitive(ctx *sql.Context, head *doltdb.Commit, ds } } case doltdb.IgnoreTableName: + if resolve.UseSearchPath && db.schemaName == "" { + schemaName, err := resolve.FirstExistingSchemaOnSearchPath(ctx, root) + if err != nil { + return nil, false, err + } + db.schemaName = schemaName + } + backingTable, _, err := db.getTable(ctx, root, doltdb.IgnoreTableName) if err != nil { return nil, false, err } if backingTable == nil { - dt, found = dtables.NewEmptyIgnoreTable(ctx), true + dt, found = dtables.NewEmptyIgnoreTable(ctx, db.schemaName), true } else { versionableTable := backingTable.(dtables.VersionableTable) - dt, found = dtables.NewIgnoreTable(ctx, versionableTable), true + dt, found = dtables.NewIgnoreTable(ctx, versionableTable, db.schemaName), true } case doltdb.GetDocTableName(), doltdb.DocTableName: isDoltgresSystemTable, err := resolve.IsDoltgresSystemTable(ctx, tname, root) diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_rebase.go b/go/libraries/doltcore/sqle/dprocedures/dolt_rebase.go index 82804af689a..543c3d46d25 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_rebase.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_rebase.go @@ -513,12 +513,15 @@ func filterIgnoredTables(ctx *sql.Context, unstagedTableDeltas []diff.TableDelta } filteredTableDeltas := make([]diff.TableDelta, 0, len(unstagedTableDeltas)) - ignorePatterns, err := doltdb.GetIgnoredTablePatterns(ctx, roots) + + schemas := diff.GetUniqueSchemaNamesFromTableDeltas(unstagedTableDeltas) + ignorePatternMap, err := doltdb.GetIgnoredTablePatterns(ctx, roots, schemas) if err != nil { return nil, err } for _, tableDelta := range unstagedTableDeltas { + ignorePatterns := ignorePatternMap[tableDelta.ToName.Schema] isIgnored, err := ignorePatterns.IsTableNameIgnored(tableDelta.ToName) if err != nil { return nil, err diff --git a/go/libraries/doltcore/sqle/dtables/ignore_table.go b/go/libraries/doltcore/sqle/dtables/ignore_table.go index 7599d123dd9..dc5d9a785dd 100644 --- a/go/libraries/doltcore/sqle/dtables/ignore_table.go +++ b/go/libraries/doltcore/sqle/dtables/ignore_table.go @@ -37,6 +37,7 @@ var _ sql.IndexAddressableTable = (*IgnoreTable)(nil) // IgnoreTable is the system table that stores patterns for table names that should not be committed. type IgnoreTable struct { backingTable VersionableTable + schemaName string } func (i *IgnoreTable) Name() string { @@ -86,13 +87,13 @@ func (i *IgnoreTable) PartitionRows(context *sql.Context, partition sql.Partitio } // NewIgnoreTable creates an IgnoreTable -func NewIgnoreTable(_ *sql.Context, backingTable VersionableTable) sql.Table { - return &IgnoreTable{backingTable: backingTable} +func NewIgnoreTable(_ *sql.Context, backingTable VersionableTable, schemaName string) sql.Table { + return &IgnoreTable{backingTable: backingTable, schemaName: schemaName} } // NewEmptyIgnoreTable creates an IgnoreTable -func NewEmptyIgnoreTable(_ *sql.Context) sql.Table { - return &IgnoreTable{} +func NewEmptyIgnoreTable(_ *sql.Context, schemaName string) sql.Table { + return &IgnoreTable{schemaName: schemaName} } // Replacer returns a RowReplacer for this table. The RowReplacer will have Insert and optionally Delete called once @@ -211,9 +212,8 @@ func (iw *ignoreWriter) StatementBegin(ctx *sql.Context) { iw.prevHash = &prevHash - tname := doltdb.TableName{Name: doltdb.IgnoreTableName} + tname := doltdb.TableName{Name: doltdb.IgnoreTableName, Schema: iw.it.schemaName} found, err := roots.Working.HasTable(ctx, tname) - if err != nil { iw.errDuringStatementBegin = err return