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

     1  // Copyright 2019 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 diff
    16  
    17  import (
    18  	"errors"
    19  	"io"
    20  	"time"
    21  
    22  	"github.com/dolthub/dolt/go/libraries/doltcore/row"
    23  	"github.com/dolthub/dolt/go/libraries/doltcore/rowconv"
    24  	"github.com/dolthub/dolt/go/libraries/doltcore/schema"
    25  	"github.com/dolthub/dolt/go/store/types"
    26  )
    27  
    28  const (
    29  	From = "from"
    30  	To   = "to"
    31  )
    32  
    33  func ToColNamer(name string) string {
    34  	return To + "_" + name
    35  }
    36  
    37  func FromColNamer(name string) string {
    38  	return From + "_" + name
    39  }
    40  
    41  type RowDiffSource struct {
    42  	ad         RowDiffer
    43  	joiner     *rowconv.Joiner
    44  	oldRowConv *rowconv.RowConverter
    45  	newRowConv *rowconv.RowConverter
    46  	warnFn     rowconv.WarnFunction
    47  }
    48  
    49  func NewRowDiffSource(ad RowDiffer, joiner *rowconv.Joiner, warnFn rowconv.WarnFunction) *RowDiffSource {
    50  	return &RowDiffSource{
    51  		ad:         ad,
    52  		joiner:     joiner,
    53  		oldRowConv: rowconv.IdentityConverter,
    54  		newRowConv: rowconv.IdentityConverter,
    55  		warnFn:     warnFn,
    56  	}
    57  }
    58  
    59  func (rdRd *RowDiffSource) AddInputRowConversion(oldConv, newConv *rowconv.RowConverter) {
    60  	rdRd.oldRowConv = oldConv
    61  	rdRd.newRowConv = newConv
    62  }
    63  
    64  // GetSchema gets the schema of the rows that this reader will return
    65  func (rdRd *RowDiffSource) GetSchema() schema.Schema {
    66  	return rdRd.joiner.GetSchema()
    67  }
    68  
    69  // NextDiff reads a row from a table.  If there is a bad row the returned error will be non nil, and calling IsBadRow(err)
    70  // will be return true. This is a potentially non-fatal error and callers can decide if they want to continue on a bad row, or fail.
    71  func (rdRd *RowDiffSource) NextDiff() (row.Row, error) {
    72  	diffs, hasMore, err := rdRd.ad.GetDiffs(1, time.Second)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	if len(diffs) == 0 {
    78  		if !hasMore {
    79  			return nil, io.EOF
    80  		}
    81  		return nil, errors.New("timeout")
    82  	}
    83  
    84  	if len(diffs) != 1 {
    85  		panic("only a single diff requested, multiple returned.  bug in AsyncDiffer")
    86  	}
    87  
    88  	d := diffs[0]
    89  	rows := make(map[string]row.Row)
    90  	if d.OldValue != nil {
    91  		sch := rdRd.joiner.SchemaForName(From)
    92  		if !rdRd.oldRowConv.IdentityConverter {
    93  			sch = rdRd.oldRowConv.SrcSch
    94  		}
    95  
    96  		oldRow, err := row.FromNoms(sch, d.KeyValue.(types.Tuple), d.OldValue.(types.Tuple))
    97  
    98  		if err != nil {
    99  			return nil, err
   100  		}
   101  
   102  		rows[From], err = rdRd.oldRowConv.ConvertWithWarnings(oldRow, rdRd.warnFn)
   103  		if err != nil {
   104  			return nil, err
   105  		}
   106  	}
   107  
   108  	if d.NewValue != nil {
   109  		sch := rdRd.joiner.SchemaForName(To)
   110  		if !rdRd.newRowConv.IdentityConverter {
   111  			sch = rdRd.newRowConv.SrcSch
   112  		}
   113  
   114  		newRow, err := row.FromNoms(sch, d.KeyValue.(types.Tuple), d.NewValue.(types.Tuple))
   115  
   116  		if err != nil {
   117  			return nil, err
   118  		}
   119  
   120  		rows[To], err = rdRd.newRowConv.ConvertWithWarnings(newRow, rdRd.warnFn)
   121  		if err != nil {
   122  			return nil, err
   123  		}
   124  	}
   125  
   126  	joinedRow, err := rdRd.joiner.Join(rows)
   127  
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  
   132  	return joinedRow, nil
   133  }
   134  
   135  // Close should release resources being held
   136  func (rdRd *RowDiffSource) Close() error {
   137  	rdRd.ad.Close()
   138  	return nil
   139  }