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 }