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  }