renamed old/new -> from/to, tracking renames

This commit is contained in:
Andy Arthur
2020-06-03 17:07:14 -05:00
parent d1ff3624e1
commit 7fc5f9bdaf
9 changed files with 303 additions and 310 deletions

View File

@@ -32,7 +32,6 @@ import (
"github.com/liquidata-inc/dolt/go/libraries/doltcore/diff"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/doltdb"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env/actions"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/row"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/rowconv"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema"
@@ -146,199 +145,172 @@ func (cmd DiffCmd) createArgParser() *argparser.ArgParser {
// Exec executes the command
func (cmd DiffCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv) int {
ap := cmd.createArgParser()
help, _ := cli.HelpAndUsagePrinters(cli.GetCommandDocumentation(commandStr, diffDocs, ap))
help, usage := cli.HelpAndUsagePrinters(cli.GetCommandDocumentation(commandStr, diffDocs, ap))
apr := cli.ParseArgs(ap, args, help)
diffParts := SchemaAndDataDiff
fromRoot, toRoot, dArgs, err := parseDiffArgs(ctx, dEnv, apr)
if err != nil {
return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage)
}
verr := diffRoots(ctx, fromRoot, toRoot, nil, dEnv, dArgs)
return HandleVErrAndExitCode(verr, usage)
}
func parseDiffArgs(ctx context.Context, dEnv *env.DoltEnv, apr *argparser.ArgParseResults) (from, to *doltdb.RootValue, dArgs *diffArgs, err error) {
dArgs = &diffArgs{}
dArgs.diffParts = SchemaAndDataDiff
if apr.Contains(DataFlag) && !apr.Contains(SchemaFlag) {
diffParts = DataOnlyDiff
dArgs.diffParts = DataOnlyDiff
} else if apr.Contains(SchemaFlag) && !apr.Contains(DataFlag) {
diffParts = SchemaOnlyDiff
dArgs.diffParts = SchemaOnlyDiff
}
diffOutput := TabularDiffOutput
dArgs.diffOutput = TabularDiffOutput
if apr.Contains(SQLFlag) {
diffOutput = SQLDiffOutput
dArgs.diffOutput = SQLDiffOutput
}
summary := apr.Contains(SummaryFlag)
if summary {
if apr.Contains(SummaryFlag) {
if apr.Contains(SchemaFlag) || apr.Contains(DataFlag) {
cli.PrintErrln("Invalid Arguments: --summary cannot be combined with --schema or --data")
return 1
return nil, nil, nil, fmt.Errorf("invalid Arguments: --summary cannot be combined with --schema or --data")
}
diffParts = Summary
dArgs.diffParts = Summary
}
if apr.ContainsArg(doltdb.DocTableName) {
return HandleDocTableVErrAndExitCode()
}
dArgs.limit, _ = apr.GetInt(limitParam)
dArgs.where = apr.GetValueOrDefault(whereParam, "")
r1, r2, tables, docs, verr := getRoots(ctx, apr.Args(), dEnv)
// default value of 0 used to signal no limit.
limit, _ := apr.GetInt(limitParam)
if verr == nil {
whereClause := apr.GetValueOrDefault(whereParam, "")
verr = diffRoots(ctx, r1, r2, docs, dEnv, &diffArgs{diffParts, diffOutput, set.NewStrSet(tables), limit, whereClause})
}
if verr != nil {
cli.PrintErrln(verr.Verbose())
return 1
}
return 0
}
// this doesnt work correctly. Need to be able to distinguish commits from tables
func getRoots(ctx context.Context, args []string, dEnv *env.DoltEnv) (r1, r2 *doltdb.RootValue, tables []string, docs []doltdb.DocDetails, verr errhand.VerboseError) {
roots := make([]*doltdb.RootValue, 2)
i := 0
for _, arg := range args {
cs, err := doltdb.NewCommitSpec(arg, dEnv.RepoState.CWBHeadRef().String())
if err != nil {
break
}
cm, err := dEnv.DoltDB.Resolve(ctx, cs)
if err != nil {
break
}
roots[i], err = cm.GetRootValue()
if err != nil {
return nil, nil, nil, nil, errhand.BuildDError("error: failed to get root").AddCause(err).Build()
}
i++
}
args, docDetails, err := actions.GetTblsAndDocDetails(dEnv, args)
if err != nil {
return nil, nil, nil, nil, errhand.BuildDError("error: failed to read args").AddCause(err).Build()
}
if i < 2 {
roots[1] = roots[0]
wrkRoot, verr := GetWorkingWithVErr(dEnv)
if verr == nil && i == 0 {
roots[1], verr = GetStagedWithVErr(dEnv)
}
wrkRootWithDocs, err := dEnv.GetUpdatedRootWithDocs(ctx, wrkRoot, docDetails)
if err != nil {
return nil, nil, nil, nil, errhand.BuildDError("error: failed to get docs").AddCause(err).Build()
}
roots[0] = wrkRootWithDocs
if verr != nil {
return nil, nil, args, nil, verr
}
}
for ; i < len(args); i++ {
tbl := args[i]
has0, err := roots[0].HasTable(ctx, tbl)
if err != nil {
return nil, nil, nil, nil, errhand.BuildDError("error: failed to read tables").AddCause(err).Build()
}
has1, err := roots[1].HasTable(ctx, tbl)
if err != nil {
return nil, nil, nil, nil, errhand.BuildDError("error: failed to read tables").AddCause(err).Build()
}
if !(has0 || has1) {
verr := errhand.BuildDError("error: Unknown table: '%s'", tbl).Build()
return nil, nil, nil, nil, verr
}
tables = append(tables, tbl)
}
return roots[0], roots[1], tables, docDetails, nil
}
func getRootForCommitSpecStr(ctx context.Context, csStr string, dEnv *env.DoltEnv) (string, *doltdb.RootValue, errhand.VerboseError) {
cs, err := doltdb.NewCommitSpec(csStr, dEnv.RepoState.CWBHeadRef().String())
from, to, leftover, err := getRoots(ctx, dEnv, apr.Args())
if err != nil {
bdr := errhand.BuildDError(`"%s" is not a validly formatted branch, or commit reference.`, csStr)
return "", nil, bdr.AddCause(err).Build()
return nil, nil, nil, err
}
dArgs.tableSet = set.NewStrSet(leftover)
// verify table args exist in at least one root
for _, tbl := range leftover {
_, ok, err := from.GetTable(ctx, tbl)
if err != nil {
return nil, nil, nil, err
}
if ok {
continue
}
_, ok, err = to.GetTable(ctx, tbl)
if err != nil {
return nil, nil, nil, err
}
if !ok {
return nil, nil, nil, fmt.Errorf("table %s does not exist in either diff root", tbl)
}
}
return from, to, dArgs, nil
}
func getRoots(ctx context.Context, dEnv *env.DoltEnv, args []string) (from, to *doltdb.RootValue, leftover []string, err error) {
headRoot, err := dEnv.HeadRoot(ctx)
workingRoot, err := dEnv.WorkingRoot(ctx)
if err != nil {
return nil, nil, nil, err
}
if len(args) == 0 {
// `dolt diff`
from = headRoot
to = workingRoot
return from, to, nil, nil
}
from, ok := maybeResolve(ctx, dEnv, args[0])
if !ok {
// `dolt diff ...tables`
from = headRoot
to = workingRoot
leftover = args
return from, to, leftover, nil
}
if len(args) == 1 {
// `dolt diff from_commit`
to = workingRoot
return from, to, nil, nil
}
to, ok = maybeResolve(ctx, dEnv, args[1])
if !ok {
// `dolt diff from_commit ...tables`
to = workingRoot
leftover = args[1:]
return from, to, leftover, nil
}
// `dolt diff from_commit to_commit ...tables`
leftover = args[2:]
return from, to, leftover, nil
}
// todo: distinguish between non-existent CommitSpec and other errors, don't assume non-existent
func maybeResolve(ctx context.Context, dEnv *env.DoltEnv, spec string) (*doltdb.RootValue, bool) {
cs, err := doltdb.NewCommitSpec(spec, dEnv.RepoState.CWBHeadRef().String())
if err != nil {
return nil, false
}
cm, err := dEnv.DoltDB.Resolve(ctx, cs)
if err != nil {
return "", nil, errhand.BuildDError(`Unable to resolve "%s"`, csStr).AddCause(err).Build()
return nil, false
}
r, err := cm.GetRootValue()
root, err := cm.GetRootValue()
if err != nil {
return "", nil, errhand.BuildDError("error: failed to get root").AddCause(err).Build()
return nil, false
}
h, err := cm.HashOf()
if err != nil {
return "", nil, errhand.BuildDError("error: failed to get commit hash").AddCause(err).Build()
}
return h.String(), r, nil
return root, true
}
func diffRoots(ctx context.Context, r1, r2 *doltdb.RootValue, docDetails []doltdb.DocDetails, dEnv *env.DoltEnv, dArgs *diffArgs) errhand.VerboseError {
func diffRoots(ctx context.Context, fromRoot, toRoot *doltdb.RootValue, docDetails []doltdb.DocDetails, dEnv *env.DoltEnv, dArgs *diffArgs) (verr errhand.VerboseError) {
var err error
tableDeltas, err := diff.GetTableDeltas(ctx, fromRoot, toRoot)
if err != nil {
return errhand.BuildDError("error: unable to diff tables").AddCause(err).Build()
}
if dArgs.tableSet.Size() == 0 {
utn, err := doltdb.UnionTableNames(ctx, r1, r2)
// if no tables were specified as args, diff all tables
utn, err := doltdb.UnionTableNames(ctx, fromRoot, toRoot)
if err != nil {
return errhand.BuildDError("error: failed to get table names").AddCause(err).Build()
}
dArgs.tableSet.Add(utn...)
}
// todo: root ordering?
tableDeltas, err := diff.GetTableDeltas(ctx, r1, r2)
if err != nil {
return errhand.BuildDError("error: unable to diff tables").AddCause(err).Build()
}
if dArgs.diffOutput == SQLDiffOutput {
err = diff.PrintSqlTableDiffs(ctx, r1, r2, iohelp.NopWrCloser(cli.CliOut))
if err != nil {
return errhand.BuildDError("error: unable to diff tables").AddCause(err).Build()
}
}
for _, td := range tableDeltas {
// todo: match tableSet by newName, oldName or both?
if !dArgs.tableSet.Contains(td.NewName) {
if !dArgs.tableSet.Contains(td.FromName) && !dArgs.tableSet.Contains(td.ToName) {
continue
}
// todo: old/new vs to/from
tblName := td.NewName
tbl1 := td.OldTable
tbl2 := td.NewTable
tblName := td.ToName
fromTable := td.FromTable
toTable := td.ToTable
if tbl1 == nil && tbl2 == nil {
if fromTable == nil && toTable == nil {
return errhand.BuildDError("error: both tables in tableDelta are nil").Build()
}
if dArgs.diffOutput == TabularDiffOutput {
printTableDiffSummary(ctx, dEnv, tblName, tbl1, tbl2, docDetails)
printTableDiffSummary(ctx, dEnv, tblName, fromTable, toTable, docDetails)
// if we're in standard output mode, follow Git convention
// and don't print data diffs for added/dropped tables
@@ -351,68 +323,32 @@ func diffRoots(ctx context.Context, r1, r2 *doltdb.RootValue, docDetails []doltd
continue
}
var sch1 schema.Schema
var sch2 schema.Schema
var sch1Hash hash.Hash
var sch2Hash hash.Hash
rowData1 := types.EmptyMap
rowData2 := types.EmptyMap
if tbl1 != nil {
sch1, err = tbl1.GetSchema(ctx)
if err != nil {
return errhand.BuildDError("error: failed to get schema").AddCause(err).Build()
}
schRef, err := tbl1.GetSchemaRef()
if err != nil {
return errhand.BuildDError("error: failed to get schema ref").AddCause(err).Build()
}
sch1Hash = schRef.TargetHash()
rowData1, err = tbl1.GetRowData(ctx)
if err != nil {
return errhand.BuildDError("error: failed to get row data").AddCause(err).Build()
}
fromSch, toSch, err := td.GetSchemas(ctx)
if err != nil {
return errhand.BuildDError("cannot retrieve schema for table %s", td.ToName).AddCause(err).Build()
}
if tbl2 != nil {
sch2, err = tbl2.GetSchema(ctx)
if err != nil {
return errhand.BuildDError("error: failed to get schema").AddCause(err).Build()
}
if tbl1 == nil {
sch1 = sch2
}
schRef, err := tbl2.GetSchemaRef()
if err != nil {
return errhand.BuildDError("error: failed to get schema ref").AddCause(err).Build()
}
sch2Hash = schRef.TargetHash()
rowData2, err = tbl2.GetRowData(ctx)
if err != nil {
return errhand.BuildDError("error: failed to get row data").AddCause(err).Build()
}
} else {
sch2 = sch1
fromMap, toMap, err := td.GetMaps(ctx)
if err != nil {
return errhand.BuildDError("could not get row data for table %s", td.ToName).AddCause(err).Build()
}
var verr errhand.VerboseError
if dArgs.diffParts&Summary != 0 {
colLen := sch2.GetAllCols().Size()
verr = diffSummary(ctx, rowData1, rowData2, colLen)
numCols := fromSch.GetAllCols().Size()
verr = diffSummary(ctx, fromMap, toMap, numCols)
}
if dArgs.diffParts&SchemaOnlyDiff != 0 && sch1Hash != sch2Hash {
if dArgs.diffParts&SchemaOnlyDiff != 0 {
verr = diffSchemas(ctx, td, dArgs)
}
if dArgs.diffParts&DataOnlyDiff != 0 {
verr = diffRows(ctx, rowData1, rowData2, sch1, sch2, dArgs, tblName)
if td.IsDrop() && dArgs.diffOutput == SQLDiffOutput {
continue // don't output DROP TABLE statements after DROP TABLE
} else if td.IsAdd() {
fromSch = toSch
}
verr = diffRows(ctx, fromMap, toMap, fromSch, toSch, dArgs, tblName)
}
if verr != nil {
@@ -424,21 +360,23 @@ func diffRoots(ctx context.Context, r1, r2 *doltdb.RootValue, docDetails []doltd
}
func diffSchemas(ctx context.Context, td diff.TableDelta, dArgs *diffArgs) errhand.VerboseError {
fromSch, toSch, err := td.GetSchemas(ctx)
if err != nil {
return errhand.BuildDError("cannot retrieve schema for table %s", td.ToName).AddCause(err).Build()
}
if eq, _ := schema.SchemasAreEqual(fromSch, toSch); eq {
return nil
}
if dArgs.diffOutput == TabularDiffOutput {
if td.IsDrop() || td.IsAdd() {
panic("cannot perform tabular schema diff for added/dropped tables")
}
sch1, sch2, err := td.GetSchemas(ctx)
diffs, unionTags := diff.DiffSchemas(fromSch, toSch)
if err != nil {
return errhand.BuildDError("cannot retrieve schema for table %s", td.NewName).AddCause(err).Build()
}
diffs, unionTags := diff.DiffSchemas(sch1, sch2)
return tabularSchemaDiff(td.NewName, unionTags, diffs)
return tabularSchemaDiff(td.ToName, unionTags, diffs)
}
return sqlSchemaDiff(ctx, td)
@@ -523,33 +461,31 @@ func tabularSchemaDiff(tableName string, tags []uint64, diffs map[uint64]diff.Sc
}
func sqlSchemaDiff(ctx context.Context, td diff.TableDelta) errhand.VerboseError{
sch1, sch2, err := td.GetSchemas(ctx)
fromSch, toSch, err := td.GetSchemas(ctx)
if err != nil {
return errhand.BuildDError("cannot retrieve schema for table %s", td.NewName).AddCause(err).Build()
return errhand.BuildDError("cannot retrieve schema for table %s", td.ToName).AddCause(err).Build()
}
if sch1 == nil {
cli.Println(sqlfmt.DropTableStmt(td.OldName))
} else if sch2 == nil {
cli.Println(sqlfmt.CreateTableStmtWithTags(td.NewName, sch1))
if td.IsDrop() {
cli.Println(sqlfmt.DropTableStmt(td.FromName))
} else if td.IsAdd() {
cli.Println(sqlfmt.CreateTableStmtWithTags(td.ToName, toSch))
} else {
if td.OldName != td.NewName {
cli.Println(sqlfmt.RenameTableStmt(td.OldName, td.NewName))
if td.FromName != td.ToName {
cli.Println(sqlfmt.RenameTableStmt(td.FromName, td.ToName))
}
colDiffs, unionTags := diff.DiffSchemas(sch1, sch2)
colDiffs, unionTags := diff.DiffSchemas(fromSch, toSch)
for _, tag := range unionTags {
cd := colDiffs[tag]
switch cd.DiffType {
case diff.SchDiffNone:
case diff.SchDiffColAdded:
cli.Println(sqlfmt.AlterTableAddColStmt(td.NewName, sqlfmt.FmtCol(0, 0, 0, *cd.New)))
cli.Println(sqlfmt.AlterTableAddColStmt(td.ToName, sqlfmt.FmtCol(0, 0, 0, *cd.New)))
case diff.SchDiffColRemoved:
cli.Print(sqlfmt.AlterTableDropColStmt(td.NewName, cd.Old.Name))
cli.Print(sqlfmt.AlterTableDropColStmt(td.ToName, cd.Old.Name))
case diff.SchDiffColModified:
cli.Print(sqlfmt.AlterTableRenameColStmt(td.NewName, cd.Old.Name, cd.New.Name))
cli.Print(sqlfmt.AlterTableRenameColStmt(td.ToName, cd.Old.Name, cd.New.Name))
}
}
}
@@ -585,11 +521,11 @@ func fromNamer(name string) string {
return diff.From + "_" + name
}
func diffRows(ctx context.Context, newRows, oldRows types.Map, newSch, oldSch schema.Schema, dArgs *diffArgs, tblName string) errhand.VerboseError {
func diffRows(ctx context.Context, fromRows, toRows types.Map, fromSch, toSch schema.Schema, dArgs *diffArgs, tblName string) errhand.VerboseError {
joiner, err := rowconv.NewJoiner(
[]rowconv.NamedSchema{
{Name: diff.From, Sch: oldSch},
{Name: diff.To, Sch: newSch},
{Name: diff.From, Sch: fromSch},
{Name: diff.To, Sch: toSch},
},
map[string]rowconv.ColNamingFunc{diff.To: toNamer, diff.From: fromNamer},
)
@@ -598,25 +534,25 @@ func diffRows(ctx context.Context, newRows, oldRows types.Map, newSch, oldSch sc
return errhand.BuildDError("").AddCause(err).Build()
}
unionSch, ds, verr := createSplitter(newSch, oldSch, joiner, dArgs)
unionSch, ds, verr := createSplitter(fromSch, toSch, joiner, dArgs)
if verr != nil {
return verr
}
ad := diff.NewAsyncDiffer(1024)
ad.Start(ctx, newRows, oldRows)
ad.Start(ctx, fromRows, toRows)
defer ad.Close()
src := diff.NewRowDiffSource(ad, joiner)
defer src.Close()
oldColNames, verr := mapTagToColName(oldSch, unionSch)
oldColNames, verr := mapTagToColName(fromSch, unionSch)
if verr != nil {
return verr
}
newColNames, verr := mapTagToColName(newSch, unionSch)
newColNames, verr := mapTagToColName(toSch, unionSch)
if verr != nil {
return verr
@@ -654,7 +590,7 @@ func diffRows(ctx context.Context, newRows, oldRows types.Map, newSch, oldSch sc
if dArgs.diffOutput != SQLDiffOutput {
if schemasEqual {
schRow, err := untyped.NewRowFromTaggedStrings(newRows.Format(), unionSch, newColNames)
schRow, err := untyped.NewRowFromTaggedStrings(toRows.Format(), unionSch, newColNames)
if err != nil {
return errhand.BuildDError("error: creating diff header").AddCause(err).Build()
@@ -662,14 +598,14 @@ func diffRows(ctx context.Context, newRows, oldRows types.Map, newSch, oldSch sc
p.InjectRow(fwtStageName, schRow)
} else {
newSchRow, err := untyped.NewRowFromTaggedStrings(newRows.Format(), unionSch, oldColNames)
newSchRow, err := untyped.NewRowFromTaggedStrings(toRows.Format(), unionSch, oldColNames)
if err != nil {
return errhand.BuildDError("error: creating diff header").AddCause(err).Build()
}
p.InjectRowWithProps(fwtStageName, newSchRow, map[string]interface{}{diff.DiffTypeProp: diff.DiffModifiedOld})
oldSchRow, err := untyped.NewRowFromTaggedStrings(newRows.Format(), unionSch, newColNames)
oldSchRow, err := untyped.NewRowFromTaggedStrings(toRows.Format(), unionSch, newColNames)
if err != nil {
return errhand.BuildDError("error: creating diff header").AddCause(err).Build()
@@ -757,17 +693,17 @@ func mapTagToColName(sch, untypedUnionSch schema.Schema) (map[uint64]string, err
return tagToCol, nil
}
func createSplitter(newSch schema.Schema, oldSch schema.Schema, joiner *rowconv.Joiner, dArgs *diffArgs) (schema.Schema, *diff.DiffSplitter, errhand.VerboseError) {
func createSplitter(fromSch schema.Schema, toSch schema.Schema, joiner *rowconv.Joiner, dArgs *diffArgs) (schema.Schema, *diff.DiffSplitter, errhand.VerboseError) {
var unionSch schema.Schema
if dArgs.diffOutput == TabularDiffOutput {
dumbNewSch, err := dumbDownSchema(newSch)
dumbNewSch, err := dumbDownSchema(toSch)
if err != nil {
return nil, nil, errhand.BuildDError("").AddCause(err).Build()
}
dumbOldSch, err := dumbDownSchema(oldSch)
dumbOldSch, err := dumbDownSchema(fromSch)
if err != nil {
return nil, nil, errhand.BuildDError("").AddCause(err).Build()
@@ -779,12 +715,12 @@ func createSplitter(newSch schema.Schema, oldSch schema.Schema, joiner *rowconv.
}
} else {
unionSch = newSch
unionSch = toSch
}
newToUnionConv := rowconv.IdentityConverter
if newSch != nil {
newToUnionMapping, err := rowconv.TagMapping(newSch, unionSch)
if toSch != nil {
newToUnionMapping, err := rowconv.TagMapping(toSch, unionSch)
if err != nil {
return nil, nil, errhand.BuildDError("Error creating unioned mapping").AddCause(err).Build()
@@ -794,8 +730,8 @@ func createSplitter(newSch schema.Schema, oldSch schema.Schema, joiner *rowconv.
}
oldToUnionConv := rowconv.IdentityConverter
if oldSch != nil {
oldToUnionMapping, err := rowconv.TagMapping(oldSch, unionSch)
if fromSch != nil {
oldToUnionMapping, err := rowconv.TagMapping(fromSch, unionSch)
if err != nil {
return nil, nil, errhand.BuildDError("Error creating unioned mapping").AddCause(err).Build()
@@ -810,7 +746,7 @@ func createSplitter(newSch schema.Schema, oldSch schema.Schema, joiner *rowconv.
var emptyHash = hash.Hash{}
func printDocDiffs(ctx context.Context, dEnv *env.DoltEnv, tblName string, tbl1, tbl2 *doltdb.Table, docDetails []doltdb.DocDetails) {
func printDocDiffs(ctx context.Context, dEnv *env.DoltEnv, fromTbl, toTbl *doltdb.Table, docDetails []doltdb.DocDetails) {
bold := color.New(color.Bold)
if docDetails == nil {
@@ -818,14 +754,14 @@ func printDocDiffs(ctx context.Context, dEnv *env.DoltEnv, tblName string, tbl1,
}
for _, doc := range docDetails {
if tbl1 != nil {
sch1, _ := tbl1.GetSchema(ctx)
doc, _ = doltdb.AddNewerTextToDocFromTbl(ctx, tbl1, &sch1, doc)
if fromTbl != nil {
sch1, _ := fromTbl.GetSchema(ctx)
doc, _ = doltdb.AddNewerTextToDocFromTbl(ctx, fromTbl, &sch1, doc)
}
if tbl2 != nil {
sch2, _ := tbl2.GetSchema(ctx)
doc, _ = doltdb.AddValueToDocFromTbl(ctx, tbl2, &sch2, doc)
if toTbl != nil {
sch2, _ := toTbl.GetSchema(ctx)
doc, _ = doltdb.AddValueToDocFromTbl(ctx, toTbl, &sch2, doc)
}
if doc.Value != nil {
@@ -875,20 +811,21 @@ func printDeletedDoc(bold *color.Color, pk string, lines []string) {
printDiffLines(bold, lines)
}
func printTableDiffSummary(ctx context.Context, dEnv *env.DoltEnv, tblName string, tbl1, tbl2 *doltdb.Table, docDetails []doltdb.DocDetails) {
// todo: handle renames
func printTableDiffSummary(ctx context.Context, dEnv *env.DoltEnv, tblName string, fromTable, toTable *doltdb.Table, docDetails []doltdb.DocDetails) {
bold := color.New(color.Bold)
if tblName == doltdb.DocTableName {
printDocDiffs(ctx, dEnv, tblName, tbl1, tbl2, docDetails)
printDocDiffs(ctx, dEnv, fromTable, toTable, docDetails)
} else {
_, _ = bold.Printf("diff --dolt a/%[1]s b/%[1]s\n", tblName)
if tbl1 == nil {
if toTable == nil {
_, _ = bold.Println("deleted table")
} else if tbl2 == nil {
} else if fromTable == nil {
_, _ = bold.Println("added table")
} else {
h1, err := tbl1.HashOf()
h1, err := fromTable.HashOf()
if err != nil {
panic(err)
@@ -896,7 +833,7 @@ func printTableDiffSummary(ctx context.Context, dEnv *env.DoltEnv, tblName strin
_, _ = bold.Printf("--- a/%s @ %s\n", tblName, h1.String())
h2, err := tbl2.HashOf()
h2, err := toTable.HashOf()
if err != nil {
panic(err)
@@ -907,12 +844,13 @@ func printTableDiffSummary(ctx context.Context, dEnv *env.DoltEnv, tblName strin
}
}
func diffSummary(ctx context.Context, v1, v2 types.Map, colLen int) errhand.VerboseError {
// todo: change to to/from
func diffSummary(ctx context.Context, from types.Map, to types.Map, colLen int) errhand.VerboseError {
ae := atomicerr.New()
ch := make(chan diff.DiffSummaryProgress)
go func() {
defer close(ch)
err := diff.Summary(ctx, ch, v1, v2)
err := diff.Summary(ctx, ch, from, to)
ae.SetIfError(err)
}()

View File

@@ -115,6 +115,35 @@ func (cmd LsCmd) Exec(ctx context.Context, commandStr string, args []string, dEn
return HandleVErrAndExitCode(verr, usage)
}
func getRootForCommitSpecStr(ctx context.Context, csStr string, dEnv *env.DoltEnv) (string, *doltdb.RootValue, errhand.VerboseError) {
cs, err := doltdb.NewCommitSpec(csStr, dEnv.RepoState.CWBHeadRef().String())
if err != nil {
bdr := errhand.BuildDError(`"%s" is not a validly formatted branch, or commit reference.`, csStr)
return "", nil, bdr.AddCause(err).Build()
}
cm, err := dEnv.DoltDB.Resolve(ctx, cs)
if err != nil {
return "", nil, errhand.BuildDError(`Unable to resolve "%s"`, csStr).AddCause(err).Build()
}
r, err := cm.GetRootValue()
if err != nil {
return "", nil, errhand.BuildDError("error: failed to get root").AddCause(err).Build()
}
h, err := cm.HashOf()
if err != nil {
return "", nil, errhand.BuildDError("error: failed to get commit hash").AddCause(err).Build()
}
return h.String(), r, nil
}
func printUserTables(ctx context.Context, root *doltdb.RootValue, label string, verbose bool) errhand.VerboseError {
tblNames, err := doltdb.GetNonSystemTableNames(ctx, root)

View File

@@ -48,14 +48,14 @@ func tableDontDescendLists(v1, v2 types.Value) bool {
return !types.IsPrimitiveKind(kind) && kind != types.TupleKind && kind == v2.Kind() && kind != types.RefKind
}
func (ad *AsyncDiffer) Start(ctx context.Context, v1, v2 types.Map) {
func (ad *AsyncDiffer) Start(ctx context.Context, from, to types.Map) {
go func() {
defer close(ad.diffChan)
defer func() {
// Ignore a panic from Diff...
recover()
}()
diff.Diff(ctx, ad.ae, v2, v1, ad.diffChan, ad.stopChan, true, tableDontDescendLists)
diff.Diff(ctx, ad.ae, from, to, ad.diffChan, ad.stopChan, true, tableDontDescendLists)
}()
}

View File

@@ -28,12 +28,12 @@ type DiffSummaryProgress struct {
}
// Summary reports a summary of diff changes between two values
func Summary(ctx context.Context, ch chan DiffSummaryProgress, v1, v2 types.Map) error {
func Summary(ctx context.Context, ch chan DiffSummaryProgress, from, to types.Map) error {
ad := NewAsyncDiffer(1024)
ad.Start(ctx, v1, v2)
ad.Start(ctx, from, to)
defer ad.Close()
ch <- DiffSummaryProgress{OldSize: v2.Len(), NewSize: v1.Len()}
ch <- DiffSummaryProgress{OldSize: from.Len(), NewSize: to.Len()}
for !ad.IsDone() {
diffs, err := ad.GetDiffs(100, time.Millisecond)

View File

@@ -18,6 +18,7 @@ import (
"context"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema"
"github.com/liquidata-inc/dolt/go/store/hash"
"github.com/liquidata-inc/dolt/go/store/types"
"sort"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/doltdb"
@@ -271,8 +272,8 @@ type tableMatches struct {
func matchTablesForRoots(ctx context.Context, newer, older *doltdb.RootValue) (tableMatches, error) {
tm := tableMatches{}
tm.renamed = make(map[string]string)
oldTableNames := make(map[uint64]string)
oldTableHashes := make(map[uint64]hash.Hash)
FromTableNames := make(map[uint64]string)
FromTableHashes := make(map[uint64]hash.Hash)
err := older.IterTables(ctx, func(name string, table *doltdb.Table) (stop bool, err error) {
sch, err := table.GetSchema(ctx)
@@ -286,8 +287,8 @@ func matchTablesForRoots(ctx context.Context, newer, older *doltdb.RootValue) (t
}
pkTag := sch.GetPKCols().GetColumns()[0].Tag
oldTableNames[pkTag] = name
oldTableHashes[pkTag] = th
FromTableNames[pkTag] = name
FromTableHashes[pkTag] = th
return false, nil
})
@@ -307,21 +308,21 @@ func matchTablesForRoots(ctx context.Context, newer, older *doltdb.RootValue) (t
}
pkTag := sch.GetPKCols().GetColumns()[0].Tag
oldName, ok := oldTableNames[pkTag]
oldName, ok := FromTableNames[pkTag]
switch {
case !ok:
tm.added = append(tm.added, name)
case oldName != name:
tm.renamed[name] = oldName
case oldTableHashes[pkTag] != th:
case FromTableHashes[pkTag] != th:
tm.modified = append(tm.modified, name)
default:
tm.unchanged = append(tm.unchanged, name)
}
if ok {
delete(oldTableNames, pkTag) // consume table name
delete(FromTableNames, pkTag) // consume table name
}
return false, nil
@@ -332,28 +333,27 @@ func matchTablesForRoots(ctx context.Context, newer, older *doltdb.RootValue) (t
}
// all unmatched tables from older must have been dropped
for _, oldName := range oldTableNames {
for _, oldName := range FromTableNames {
tm.dropped = append(tm.dropped, oldName)
}
return tm, nil
}
// todo: to vs from
type TableDelta struct {
NewName string
OldName string
NewTable *doltdb.Table
OldTable *doltdb.Table
FromName string
ToName string
FromTable *doltdb.Table
ToTable *doltdb.Table
}
func GetTableDeltas(ctx context.Context, older, newer *doltdb.RootValue) ([]TableDelta, error) {
func GetTableDeltas(ctx context.Context, fromRoot, toRoot *doltdb.RootValue) ([]TableDelta, error) {
var deltas []TableDelta
oldTables := make(map[uint64]*doltdb.Table)
oldTableNames := make(map[uint64]string)
oldTableHashes := make(map[uint64]hash.Hash)
fromTable := make(map[uint64]*doltdb.Table)
fromTableNames := make(map[uint64]string)
fromTableHashes := make(map[uint64]hash.Hash)
err := older.IterTables(ctx, func(name string, table *doltdb.Table) (stop bool, err error) {
err := fromRoot.IterTables(ctx, func(name string, table *doltdb.Table) (stop bool, err error) {
sch, err := table.GetSchema(ctx)
if err != nil {
return true, err
@@ -365,9 +365,9 @@ func GetTableDeltas(ctx context.Context, older, newer *doltdb.RootValue) ([]Tabl
}
pkTag := sch.GetPKCols().GetColumns()[0].Tag
oldTables[pkTag] = table
oldTableNames[pkTag] = name
oldTableHashes[pkTag] = th
fromTable[pkTag] = table
fromTableNames[pkTag] = name
fromTableHashes[pkTag] = th
return false, nil
})
@@ -375,7 +375,7 @@ func GetTableDeltas(ctx context.Context, older, newer *doltdb.RootValue) ([]Tabl
return nil, err
}
err = newer.IterTables(ctx, func(name string, table *doltdb.Table) (stop bool, err error) {
err = toRoot.IterTables(ctx, func(name string, table *doltdb.Table) (stop bool, err error) {
sch, err := table.GetSchema(ctx)
if err != nil {
return true, err
@@ -387,21 +387,21 @@ func GetTableDeltas(ctx context.Context, older, newer *doltdb.RootValue) ([]Tabl
}
pkTag := sch.GetPKCols().GetColumns()[0].Tag
oldName, ok := oldTableNames[pkTag]
oldName, ok := fromTableNames[pkTag]
if !ok {
deltas = append(deltas, TableDelta{NewName: name, NewTable: table})
} else if oldName != name || oldTableHashes[pkTag] != th {
deltas = append(deltas, TableDelta{ToName: name, ToTable: table})
} else if oldName != name || fromTableHashes[pkTag] != th {
deltas = append(deltas, TableDelta{
NewName: name,
OldName: oldTableNames[pkTag],
NewTable: table,
OldTable: oldTables[pkTag],
ToName: name,
FromName: fromTableNames[pkTag],
ToTable: table,
FromTable: fromTable[pkTag],
})
}
if ok {
delete(oldTableNames, pkTag) // consume table name
delete(fromTableNames, pkTag) // consume table name
}
return false, nil
@@ -411,38 +411,64 @@ func GetTableDeltas(ctx context.Context, older, newer *doltdb.RootValue) ([]Tabl
return nil, err
}
// all unmatched tables from older must have been dropped
for pkTag, oldName := range oldTableNames {
deltas = append(deltas, TableDelta{OldName: oldName, OldTable: oldTables[pkTag]})
// all unmatched tables in fromRoot must have been dropped
for pkTag, oldName := range fromTableNames {
deltas = append(deltas, TableDelta{FromName: oldName, FromTable: fromTable[pkTag]})
}
return deltas, nil
}
func (td TableDelta) IsAdd() bool {
return td.OldTable == nil && td.NewTable != nil
return td.FromTable == nil && td.ToTable != nil
}
func (td TableDelta) IsDrop() bool {
return td.OldTable != nil && td.NewTable == nil
return td.FromTable != nil && td.ToTable == nil
}
func (td TableDelta) GetSchemas(ctx context.Context) (new, old schema.Schema, err error) {
if td.OldTable != nil {
old, err = td.OldTable.GetSchema(ctx)
func (td TableDelta) GetSchemas(ctx context.Context) (from, to schema.Schema, err error) {
if td.FromTable != nil {
from, err = td.FromTable.GetSchema(ctx)
if err != nil {
return nil, nil, err
}
} else {
from = schema.EmptySchema
}
if td.NewTable != nil {
new, err = td.NewTable.GetSchema(ctx)
if td.ToTable != nil {
to, err = td.ToTable.GetSchema(ctx)
if err != nil {
return nil, nil, err
}
} else {
to = schema.EmptySchema
}
return new, old, nil
return from, to, nil
}
func (td TableDelta) GetMaps(ctx context.Context) (from, to types.Map, err error) {
if td.FromTable != nil {
from, err = td.FromTable.GetRowData(ctx)
if err != nil {
return from, to, err
}
} else {
from, _ = types.NewMap(ctx, td.ToTable.ValueReadWriter())
}
if td.ToTable != nil {
to, err = td.ToTable.GetRowData(ctx)
if err != nil {
return from, to, err
}
} else {
to, _ = types.NewMap(ctx, td.FromTable.ValueReadWriter())
}
return from, to, nil
}

View File

@@ -42,8 +42,8 @@ type SchemaDifference struct {
type columnPair [2]*schema.Column
// DiffSchemas compares two schemas by looking at columns with the same tag.
func DiffSchemas(sch1, sch2 schema.Schema) (map[uint64]SchemaDifference, []uint64) {
colPairMap, unionTags := pairColumns(sch1, sch2)
func DiffSchemas(fromSch, toSch schema.Schema) (map[uint64]SchemaDifference, []uint64) {
colPairMap, unionTags := pairColumns(fromSch, toSch)
diffs := make(map[uint64]SchemaDifference)
for _, tag := range unionTags {
@@ -63,19 +63,19 @@ func DiffSchemas(sch1, sch2 schema.Schema) (map[uint64]SchemaDifference, []uint6
}
// pairColumns loops over both sets of columns pairing columns with the same tag.
func pairColumns(sch1, sch2 schema.Schema) (map[uint64]columnPair, []uint64) {
// collect the tag union of the two schemas, ordering sch1 before sch2
func pairColumns(fromSch, toSch schema.Schema) (map[uint64]columnPair, []uint64) {
// collect the tag union of the two schemas, ordering fromSch before toSch
var unionTags []uint64
colPairMap := make(map[uint64]columnPair)
_ = sch1.GetAllCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
_ = fromSch.GetAllCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
colPairMap[tag] = columnPair{&col, nil}
unionTags = append(unionTags, tag)
return false, nil
})
_ = sch2.GetAllCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
_ = toSch.GetAllCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
if pair, ok := colPairMap[tag]; ok {
pair[1] = &col
colPairMap[tag] = pair

View File

@@ -226,7 +226,7 @@ func calcTableMergeStats(ctx context.Context, tbl *doltdb.Table, mergeTbl *doltd
ch := make(chan diff.DiffSummaryProgress)
go func() {
defer close(ch)
err := diff.Summary(ctx, ch, mergeRows, rows)
err := diff.Summary(ctx, ch, rows, mergeRows)
ae.SetIfError(err)
}()

View File

@@ -476,7 +476,7 @@ func replayRowDiffs(ctx context.Context, vrw types.ValueReadWriter, rSch schema.
ad := diff.NewAsyncDiffer(diffBufSize)
// get all differences (including merges) between original commit and its parent
ad.Start(ctx, rows, parentRows)
ad.Start(ctx, parentRows, rows)
defer ad.Close()
for {

View File

@@ -288,7 +288,7 @@ type commitInfo struct {
func newDiffRowItr(ctx context.Context, joiner *rowconv.Joiner, rowDataFrom, rowDataTo types.Map, convFrom, convTo *rowconv.RowConverter, from, to commitInfo) *diffRowItr {
ad := diff.NewAsyncDiffer(1024)
ad.Start(ctx, rowDataTo, rowDataFrom)
ad.Start(ctx, rowDataFrom, rowDataTo)
src := diff.NewRowDiffSource(ad, joiner)
src.AddInputRowConversion(convFrom, convTo)