diff --git a/go/libraries/doltcore/diff/async_differ.go b/go/libraries/doltcore/diff/async_differ.go index 1fc8c557ec..1a114d1ac3 100644 --- a/go/libraries/doltcore/diff/async_differ.go +++ b/go/libraries/doltcore/diff/async_differ.go @@ -19,6 +19,7 @@ import ( "fmt" "time" + "github.com/dolthub/go-mysql-server/sql" "golang.org/x/sync/errgroup" "github.com/dolthub/dolt/go/libraries/doltcore/row" @@ -75,6 +76,16 @@ type RowDiffer interface { Close() error } +// SqlRowDiffWriter knows how to write diff rows to an arbitrary format and destination. +type SqlRowDiffWriter interface { + // WriteRow writes the diff row given, of the diff type provided. colDiffTypes is guaranteed to be the same length as + // the input row. + WriteRow(ctx context.Context, row sql.Row, diffType ChangeType, colDiffTypes []ChangeType) error + + // Close finalizes the work of this writer. + Close(ctx context.Context) error +} + func NewRowDiffer(ctx context.Context, fromSch, toSch schema.Schema, buf int) RowDiffer { ad := NewAsyncDiffer(buf) diff --git a/go/libraries/doltcore/table/untyped/sqlexport/sql_diff_writer.go b/go/libraries/doltcore/table/untyped/sqlexport/sql_diff_writer.go index 7943637692..44e702b580 100755 --- a/go/libraries/doltcore/table/untyped/sqlexport/sql_diff_writer.go +++ b/go/libraries/doltcore/table/untyped/sqlexport/sql_diff_writer.go @@ -15,27 +15,85 @@ package sqlexport import ( + "context" + "fmt" "io" + "github.com/dolthub/dolt/go/libraries/doltcore/diff" + "github.com/dolthub/dolt/go/libraries/doltcore/schema" + "github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlfmt" "github.com/dolthub/dolt/go/libraries/doltcore/table/editor" + "github.com/dolthub/dolt/go/libraries/utils/iohelp" + "github.com/dolthub/dolt/go/libraries/utils/set" "github.com/dolthub/go-mysql-server/sql" ) type SqlDiffWriter struct { tableName string - sch sql.Schema + sch schema.Schema writtenFirstRow bool writtenAutocommitOff bool - writeCloser io.WriteCloser + writeCloser io.WriteCloser editOpts editor.Options autocommitOff bool } -func NewSqlDiffWriter(tableName string, schema sql.Schema, wr io.WriteCloser) *SqlDiffWriter { +func NewSqlDiffWriter(tableName string, schema schema.Schema, wr io.WriteCloser) *SqlDiffWriter { return &SqlDiffWriter{ - tableName: tableName, - sch: schema, - writtenFirstRow: false, - writeCloser: wr, + tableName: tableName, + sch: schema, + writtenFirstRow: false, + writeCloser: wr, } } + +func (w SqlDiffWriter) WriteRow( + ctx context.Context, + row sql.Row, + rowDiffType diff.ChangeType, + colDiffTypes []diff.ChangeType, +) error { + if len(row) != len(colDiffTypes) { + return fmt.Errorf("expected the same size for columns and diff types, got %d and %d", len(row), len(colDiffTypes)) + } + + switch rowDiffType { + case diff.Inserted: + stmt, err := sqlfmt.SqlRowAsInsertStmt(row, w.tableName, w.sch) + if err != nil { + return err + } + + return iohelp.WriteLine(w.writeCloser, stmt) + case diff.Deleted: + stmt, err := sqlfmt.SqlRowAsDeleteStmt(row, w.tableName, w.sch) + if err != nil { + return err + } + + return iohelp.WriteLine(w.writeCloser, stmt) + case diff.ModifiedNew: + updatedCols := set.NewEmptyStrSet() + for i, diffType := range colDiffTypes { + if diffType != diff.None { + updatedCols.Add(w.sch.GetAllCols().GetByIndex(i).Name) + } + } + + stmt, err := sqlfmt.SqlRowAsUpdateStmt(row, w.tableName, w.sch, updatedCols) + if err != nil { + return err + } + + return iohelp.WriteLine(w.writeCloser, stmt) + case diff.ModifiedOld: + // do nothing, we only issue UPDATE for ModifiedNew + return nil + default: + return fmt.Errorf("unexpected row diff type: %v", rowDiffType) + } +} + +func (w SqlDiffWriter) Close(ctx context.Context) error { + return w.writeCloser.Close() +} diff --git a/go/libraries/doltcore/table/untyped/tabular/fixedwidth_diff_tablewriter.go b/go/libraries/doltcore/table/untyped/tabular/fixedwidth_diff_tablewriter.go index cd4fd2cd96..f1999dc970 100755 --- a/go/libraries/doltcore/table/untyped/tabular/fixedwidth_diff_tablewriter.go +++ b/go/libraries/doltcore/table/untyped/tabular/fixedwidth_diff_tablewriter.go @@ -82,7 +82,7 @@ func colorsForDiffTypes(colDiffTypes []diff.ChangeType) []*color.Color { return colors } -func (w FixedWidthDiffTableWriter) Close(ctx *sql.Context) error { +func (w FixedWidthDiffTableWriter) Close(ctx context.Context) error { return w.tableWriter.Close(ctx) } diff --git a/go/libraries/utils/set/strset.go b/go/libraries/utils/set/strset.go index 1b3590e3dd..6c55ff90ea 100644 --- a/go/libraries/utils/set/strset.go +++ b/go/libraries/utils/set/strset.go @@ -31,15 +31,17 @@ type StrSet struct { func newStrSet(items []string, caseSensitive bool) *StrSet { s := &StrSet{make(map[string]bool, len(items)), caseSensitive} - if items != nil { - for _, item := range items { - s.items[item] = true - } + for _, item := range items { + s.items[item] = true } return s } +func NewEmptyStrSet() *StrSet { + return newStrSet(nil, true) +} + func NewStrSet(items []string) *StrSet { return newStrSet(items, true) }