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