github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/merge/stash.go (about)

     1  // Copyright 2022 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package merge
    16  
    17  import (
    18  	"context"
    19  
    20  	"github.com/dolthub/dolt/go/libraries/doltcore/conflict"
    21  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
    22  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb/durable"
    23  	"github.com/dolthub/dolt/go/store/types"
    24  )
    25  
    26  type conflictStash struct {
    27  	Stash map[string]*conflictData
    28  }
    29  
    30  type conflictData struct {
    31  	HasConflicts bool
    32  	Sch          conflict.ConflictSchema
    33  	ConfIdx      durable.ConflictIndex
    34  }
    35  
    36  // Empty returns false if any table has a conflict.
    37  // True otherwise.
    38  func (s *conflictStash) Empty() bool {
    39  	for _, data := range s.Stash {
    40  		if data.HasConflicts {
    41  			return false
    42  		}
    43  	}
    44  	return true
    45  }
    46  
    47  type violationStash struct {
    48  	// todo: durable
    49  	Stash map[string]types.Map
    50  }
    51  
    52  // Empty returns false if any table has constraint violations.
    53  // True otherwise.
    54  func (s *violationStash) Empty() bool {
    55  	for _, data := range s.Stash {
    56  		if data.Len() > 0 {
    57  			return false
    58  		}
    59  	}
    60  	return true
    61  }
    62  
    63  func stashConflicts(ctx context.Context, root doltdb.RootValue) (doltdb.RootValue, *conflictStash, error) {
    64  	names, err := root.GetTableNames(ctx, doltdb.DefaultSchemaName)
    65  	if err != nil {
    66  		return nil, nil, err
    67  	}
    68  
    69  	updatedRoot := root
    70  	stash := make(map[string]*conflictData, len(names))
    71  	for _, name := range names {
    72  		tbl, _, err := root.GetTable(ctx, doltdb.TableName{Name: name})
    73  		if err != nil {
    74  			return nil, nil, err
    75  		}
    76  		d, err := getConflictData(ctx, tbl)
    77  		if err != nil {
    78  			return nil, nil, err
    79  		}
    80  		stash[name] = d
    81  		tbl, err = tbl.ClearConflicts(ctx)
    82  		if err != nil {
    83  			return nil, nil, err
    84  		}
    85  		updatedRoot, err = updatedRoot.PutTable(ctx, doltdb.TableName{Name: name}, tbl)
    86  		if err != nil {
    87  			return nil, nil, err
    88  		}
    89  	}
    90  
    91  	return updatedRoot, &conflictStash{stash}, nil
    92  }
    93  
    94  func stashViolations(ctx context.Context, root doltdb.RootValue) (doltdb.RootValue, *violationStash, error) {
    95  	names, err := root.GetTableNames(ctx, doltdb.DefaultSchemaName)
    96  	if err != nil {
    97  		return nil, nil, err
    98  	}
    99  
   100  	updatedRoot := root
   101  	stash := make(map[string]types.Map, len(names))
   102  	for _, name := range names {
   103  		tbl, _, err := root.GetTable(ctx, doltdb.TableName{Name: name})
   104  		if err != nil {
   105  			return nil, nil, err
   106  		}
   107  		v, err := tbl.GetConstraintViolations(ctx)
   108  		stash[name] = v
   109  		tbl, err = tbl.SetConstraintViolations(ctx, types.EmptyMap)
   110  		if err != nil {
   111  			return nil, nil, err
   112  		}
   113  		updatedRoot, err = updatedRoot.PutTable(ctx, doltdb.TableName{Name: name}, tbl)
   114  		if err != nil {
   115  			return nil, nil, err
   116  		}
   117  	}
   118  
   119  	return updatedRoot, &violationStash{stash}, nil
   120  }
   121  
   122  // applyConflictStash applies the data in |stash| to the root value. Missing
   123  // tables will be skipped. This function will override any previous conflict
   124  // data.
   125  func applyConflictStash(ctx context.Context, stash map[string]*conflictData, root doltdb.RootValue) (doltdb.RootValue, error) {
   126  	updatedRoot := root
   127  	for name, data := range stash {
   128  		tbl, ok, err := root.GetTable(ctx, doltdb.TableName{Name: name})
   129  		if err != nil {
   130  			return nil, err
   131  		}
   132  		if !ok {
   133  			continue
   134  		}
   135  		tbl, err = setConflictData(ctx, tbl, data)
   136  		if err != nil {
   137  			return nil, err
   138  		}
   139  		updatedRoot, err = updatedRoot.PutTable(ctx, doltdb.TableName{Name: name}, tbl)
   140  		if err != nil {
   141  			return nil, err
   142  		}
   143  	}
   144  
   145  	return updatedRoot, nil
   146  }
   147  
   148  func getConflictData(ctx context.Context, tbl *doltdb.Table) (*conflictData, error) {
   149  	var sch conflict.ConflictSchema
   150  	var confIdx durable.ConflictIndex
   151  
   152  	hasCnf, err := tbl.HasConflicts(ctx)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  	if hasCnf {
   157  		sch, confIdx, err = tbl.GetConflicts(ctx)
   158  		if err != nil {
   159  			return nil, err
   160  		}
   161  	}
   162  
   163  	return &conflictData{
   164  		HasConflicts: hasCnf,
   165  		Sch:          sch,
   166  		ConfIdx:      confIdx,
   167  	}, nil
   168  }
   169  
   170  func setConflictData(ctx context.Context, tbl *doltdb.Table, data *conflictData) (*doltdb.Table, error) {
   171  	var err error
   172  	if !data.HasConflicts {
   173  		tbl, err = tbl.ClearConflicts(ctx)
   174  	} else {
   175  		tbl, err = tbl.SetConflicts(ctx, data.Sch, data.ConfIdx)
   176  	}
   177  	if err != nil {
   178  		return nil, err
   179  	}
   180  
   181  	return tbl, nil
   182  }