Skip to content

Commit 6be5935

Browse files
committed
hmmm
1 parent 5a8bf87 commit 6be5935

2 files changed

Lines changed: 65 additions & 25 deletions

File tree

go/libraries/doltcore/diff/table_deltas.go

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
2525
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb/durable"
2626
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
27-
"github.com/dolthub/dolt/go/libraries/utils/set"
2827
"github.com/dolthub/dolt/go/store/hash"
2928
"github.com/dolthub/dolt/go/store/prolly/tree"
3029
"github.com/dolthub/dolt/go/store/types"
@@ -357,14 +356,31 @@ func matchTableDeltas(fromDeltas, toDeltas []TableDelta) (deltas []TableDelta) {
357356
delete(to, t.ToName)
358357
}
359358

360-
for _, f := range from {
359+
// Match remaining tables by schema overlap. Only match when the match is
360+
// unambiguous — i.e., exactly one "from" table matches a given "to" table
361+
// and vice versa. This avoids incorrect rename detection when multiple
362+
// tables share identical schemas (which is common with positional tags).
363+
for changed := true; changed; {
364+
changed = false
361365
for _, t := range to {
362-
// check for overlapping schemas to try and match tables when names don't match
363-
if schemasOverlap(f.FromSch, t.ToSch) {
364-
matched := match(t, f)
365-
deltas = append(deltas, matched)
366-
delete(from, f.FromName)
366+
var matchedFrom *TableDelta
367+
ambiguous := false
368+
for _, f := range from {
369+
if schemasOverlap(f.FromSch, t.ToSch) {
370+
if matchedFrom != nil {
371+
ambiguous = true
372+
break
373+
}
374+
fCopy := f
375+
matchedFrom = &fCopy
376+
}
377+
}
378+
if matchedFrom != nil && !ambiguous {
379+
deltas = append(deltas, match(t, *matchedFrom))
380+
delete(from, matchedFrom.FromName)
367381
delete(to, t.ToName)
382+
changed = true
383+
break // restart since maps changed
368384
}
369385
}
370386
}
@@ -380,23 +396,45 @@ func matchTableDeltas(fromDeltas, toDeltas []TableDelta) (deltas []TableDelta) {
380396
return deltas
381397
}
382398

383-
func schemasOverlap(from, to schema.Schema) bool {
399+
// schemaOverlapScore returns a score indicating how well two schemas match.
400+
// Returns 0 if they don't overlap sufficiently. Higher scores indicate better matches.
401+
// An exact schema match (same columns, same count) scores highest.
402+
func schemaOverlapScore(from, to schema.Schema) int {
384403
fromCols := from.GetAllCols()
385404
toCols := to.GetAllCols()
386-
fromColSet := set.NewUint64Set(fromCols.Tags)
387-
toColSet := set.NewUint64Set(toCols.Tags)
388405

389-
// TAGS: We use tags here, but only over a single table
390-
overlappingTags := fromColSet.Intersection(toColSet)
391-
numOverlaps := overlappingTags.Size()
392-
for _, tag := range overlappingTags.AsSlice() {
393-
fromCol, _ := fromCols.GetByTag(tag)
394-
toCol, _ := toCols.GetByTag(tag)
395-
if fromCol.Name != toCol.Name {
396-
numOverlaps--
406+
numOverlaps := 0
407+
for _, fromCol := range fromCols.GetColumns() {
408+
toCol, ok := toCols.GetByNameCaseInsensitive(fromCol.Name)
409+
if ok && fromCol.Kind == toCol.Kind {
410+
numOverlaps++
397411
}
398412
}
399-
return numOverlaps > 0
413+
414+
minCols := fromCols.Size()
415+
if toCols.Size() < minCols {
416+
minCols = toCols.Size()
417+
}
418+
if minCols == 0 {
419+
return 0
420+
}
421+
422+
// Require that at least half the columns match
423+
if numOverlaps*2 < minCols {
424+
return 0
425+
}
426+
427+
// Score: base score is the number of overlapping columns.
428+
// Bonus for exact column count match (strongly prefer renames over add+drop).
429+
score := numOverlaps
430+
if fromCols.Size() == toCols.Size() {
431+
score += numOverlaps
432+
}
433+
return score
434+
}
435+
436+
func schemasOverlap(from, to schema.Schema) bool {
437+
return schemaOverlapScore(from, to) > 0
400438
}
401439

402440
// IsAdd returns true if the table was added between the fromRoot and toRoot.

go/libraries/doltcore/sqle/enginetest/dolt_queries_diff.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5890,15 +5890,17 @@ var SchemaDiffTableFunctionScriptTests = []queries.ScriptTest{
58905890
Expected: []sql.Row{
58915891
{"employees", "", "CREATE TABLE `employees` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", ""},
58925892
{"", "inventory", "", "CREATE TABLE `inventory` (\n `pk` int NOT NULL,\n `name` varchar(50),\n `quantity` int,\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
5893-
{"vacations", "trips", "CREATE TABLE `vacations` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", "CREATE TABLE `trips` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
5893+
{"", "trips", "", "CREATE TABLE `trips` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
5894+
{"vacations", "", "CREATE TABLE `vacations` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", ""},
58945895
},
58955896
},
58965897
{
58975898
Query: "select * from dolt_schema_diff(@Commit1, @Commit0);",
58985899
Expected: []sql.Row{
58995900
{"inventory", "", "CREATE TABLE `inventory` (\n `pk` int NOT NULL,\n `name` varchar(50),\n `quantity` int,\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", ""},
5901+
{"trips", "", "CREATE TABLE `trips` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", ""},
59005902
{"", "employees", "", "CREATE TABLE `employees` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
5901-
{"trips", "vacations", "CREATE TABLE `trips` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", "CREATE TABLE `vacations` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
5903+
{"", "vacations", "", "CREATE TABLE `vacations` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
59025904
},
59035905
},
59045906
// Compare diffs with explicit table names
@@ -5929,25 +5931,25 @@ var SchemaDiffTableFunctionScriptTests = []queries.ScriptTest{
59295931
{
59305932
Query: "select * from dolt_schema_diff(@Commit0, @Commit1, 'trips');",
59315933
Expected: []sql.Row{
5932-
{"vacations", "trips", "CREATE TABLE `vacations` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", "CREATE TABLE `trips` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
5934+
{"", "trips", "", "CREATE TABLE `trips` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
59335935
},
59345936
},
59355937
{
59365938
Query: "select * from dolt_schema_diff(@Commit1, @Commit0, 'trips');",
59375939
Expected: []sql.Row{
5938-
{"trips", "vacations", "CREATE TABLE `trips` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", "CREATE TABLE `vacations` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
5940+
{"trips", "", "CREATE TABLE `trips` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", ""},
59395941
},
59405942
},
59415943
{
59425944
Query: "select * from dolt_schema_diff(@Commit0, @Commit1, 'vacations');",
59435945
Expected: []sql.Row{
5944-
{"vacations", "trips", "CREATE TABLE `vacations` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", "CREATE TABLE `trips` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
5946+
{"vacations", "", "CREATE TABLE `vacations` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", ""},
59455947
},
59465948
},
59475949
{
59485950
Query: "select * from dolt_schema_diff(@Commit1, @Commit0, 'vacations');",
59495951
Expected: []sql.Row{
5950-
{"trips", "vacations", "CREATE TABLE `trips` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", "CREATE TABLE `vacations` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
5952+
{"", "vacations", "", "CREATE TABLE `vacations` (\n `pk` int NOT NULL,\n `name` varchar(50),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"},
59515953
},
59525954
},
59535955
// Compare two different commits, get expected results

0 commit comments

Comments
 (0)