github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/metastore/diff.go (about) 1 package metastore 2 3 import ( 4 "sort" 5 6 "github.com/treeverse/lakefs/pkg/catalog" 7 ) 8 9 type MetaDiff struct { 10 PartitionDiff catalog.Differences 11 ColumnsDiff catalog.Differences 12 } 13 14 type CompareResult int 15 16 const ( 17 ItemLess CompareResult = iota 18 ItemSameKey 19 ItemSame 20 ItemGreater 21 ) 22 23 type Collection interface { 24 sort.Interface 25 Value(i int) interface{} 26 Name(i int) string 27 CompareWith(i int, v interface{}, j int) CompareResult 28 } 29 30 type DiffCallbackFn func(difference catalog.DifferenceType, iter interface{}, name string) error 31 32 func DiffIterable(iterA, iterB Collection, callbackFn DiffCallbackFn) error { 33 sort.Sort(iterA) 34 sort.Sort(iterB) 35 i, j, sizeA, sizeB := 0, 0, iterA.Len(), iterB.Len() 36 for i < sizeA && j < sizeB { 37 switch iterA.CompareWith(i, iterB, j) { 38 case ItemSameKey: 39 err := callbackFn(catalog.DifferenceTypeChanged, iterA.Value(i), iterA.Name(i)) 40 if err != nil { 41 return err 42 } 43 i++ 44 j++ 45 46 case ItemSame: 47 i++ 48 j++ 49 50 case ItemGreater: 51 err := callbackFn(catalog.DifferenceTypeRemoved, iterB.Value(j), iterB.Name(j)) 52 if err != nil { 53 return err 54 } 55 j++ 56 57 case ItemLess: 58 err := callbackFn(catalog.DifferenceTypeAdded, iterA.Value(i), iterA.Name(i)) 59 if err != nil { 60 return err 61 } 62 i++ 63 } 64 } 65 66 for j < sizeB { 67 err := callbackFn(catalog.DifferenceTypeRemoved, iterB.Value(j), iterB.Name(j)) 68 if err != nil { 69 return err 70 } 71 j++ 72 } 73 for i < sizeA { 74 err := callbackFn(catalog.DifferenceTypeAdded, iterA.Value(i), iterA.Name(i)) 75 if err != nil { 76 return err 77 } 78 i++ 79 } 80 return nil 81 } 82 83 func Diff(iterA, iterB Collection) (catalog.Differences, error) { 84 var diff catalog.Differences 85 err := DiffIterable(iterA, iterB, func(diffType catalog.DifferenceType, _ interface{}, name string) error { 86 diff = append(diff, catalog.Difference{ 87 Type: diffType, 88 DBEntry: catalog.NewDBEntryBuilder().Path(name).Build(), 89 }) 90 return nil 91 }) 92 if err != nil { 93 return nil, err 94 } 95 return diff, nil 96 }