Use processTableDelta logic in td.GetSummary

This commit is contained in:
Taylor Bantle
2023-02-24 10:27:37 -08:00
parent 89a145b95a
commit 2f818e903c
3 changed files with 89 additions and 140 deletions
+4 -57
View File
@@ -479,7 +479,7 @@ func maybeResolve(ctx context.Context, dEnv *env.DoltEnv, spec string) (*doltdb.
return root, true
}
func printDiffSummary(ctx context.Context, tds []diff.TableDelta, engine *engine.SqlEngine, dArgs *diffArgs) errhand.VerboseError {
func printDiffSummary(ctx context.Context, tds []diff.TableDelta, ddb *doltdb.DoltDB, dArgs *diffArgs) errhand.VerboseError {
sqlSch := sql.Schema{
&sql.Column{Name: "Table name", Type: types.Text, Nullable: false},
&sql.Column{Name: "Diff Type", Type: types.Text, Nullable: false},
@@ -500,17 +500,12 @@ func printDiffSummary(ctx context.Context, tds []diff.TableDelta, engine *engine
return errhand.BuildDError("error: both tables in tableDelta are nil").Build()
}
dataChanged, verr := getDataHasChanged(ctx, engine, td, dArgs)
if verr != nil {
return verr
}
summ, err := td.GetSummary(ctx, dataChanged)
summ, err := td.GetSummary(ctx)
if err != nil {
return errhand.BuildDError("could not get table delta summary").AddCause(err).Build()
}
err = wr.WriteSqlRow(ctx, sql.Row{td.CurName(), summ.DiffType, dataChanged, summ.HasSchemaChanges})
err = wr.WriteSqlRow(ctx, sql.Row{td.CurName(), summ.DiffType, summ.DataChange, summ.SchemaChange})
if err != nil {
return errhand.BuildDError("could not write table delta summary").AddCause(err).Build()
}
@@ -537,7 +532,7 @@ func diffUserTables(ctx context.Context, dEnv *env.DoltEnv, dArgs *diffArgs) err
})
if dArgs.diffParts&Summary != 0 {
return printDiffSummary(ctx, tableDeltas, engine, dArgs)
return printDiffSummary(ctx, tableDeltas, dEnv.DoltDB, dArgs)
}
dw, err := newDiffWriter(dArgs.diffOutput)
@@ -719,54 +714,6 @@ func sqlSchemaDiff(ctx context.Context, td diff.TableDelta, toSchemas map[string
return ddlStatements, nil
}
func getDataHasChanged(ctx context.Context,
se *engine.SqlEngine,
td diff.TableDelta,
dArgs *diffArgs,
) (bool, errhand.VerboseError) {
diffable := schema.ArePrimaryKeySetsDiffable(td.Format(), td.FromSch, td.ToSch)
canSqlDiff := !(td.ToSch == nil || (td.FromSch != nil && !schema.SchemasAreEqual(td.FromSch, td.ToSch)))
// can't diff
if !diffable {
// TODO: this messes up some structured output if the user didn't redirect it
cli.PrintErrf("Primary key sets differ between revisions for table %s, skipping data diff\n", td.ToName)
return false, nil
} else if dArgs.diffOutput == SQLDiffOutput && !canSqlDiff {
// TODO: this is overly broad, we can absolutely do better
_, _ = fmt.Fprintf(cli.CliErr, "Incompatible schema change, skipping data diff\n")
return false, nil
}
tableName := td.CurName()
columns := getColumnNamesString(td.FromSch, td.ToSch)
query := fmt.Sprintf("select %s, %s from dolt_diff('%s', '%s', '%s') limit 1", columns, "diff_type", dArgs.fromRef, dArgs.toRef, tableName)
sqlCtx, err := engine.NewLocalSqlContext(ctx, se)
if err != nil {
return false, errhand.VerboseErrorFromError(err)
}
_, rowIter, err := se.Query(sqlCtx, query)
if sql.ErrSyntaxError.Is(err) {
return false, errhand.BuildDError("Failed to parse diff query. Invalid where clause?\nDiff query: %s", query).AddCause(err).Build()
} else if err != nil {
return false, errhand.BuildDError("Error running diff query:\n%s", query).AddCause(err).Build()
}
defer rowIter.Close(sqlCtx)
_, err = rowIter.Next(sqlCtx)
if err == io.EOF {
return false, nil
} else if err != nil {
return false, errhand.VerboseErrorFromError(err)
}
return true, nil
}
func diffRows(
ctx context.Context,
se *engine.SqlEngine,
+74 -10
View File
@@ -58,10 +58,10 @@ type TableDelta struct {
}
type TableDeltaSummary struct {
DiffType string
HasDataChanges bool
HasSchemaChanges bool
TableName string
DiffType string
DataChange bool
SchemaChange bool
TableName string
}
// GetStagedUnstagedTableDeltas represents staged and unstaged changes as TableDelta slices.
@@ -287,13 +287,16 @@ func (td TableDelta) IsRename() bool {
return td.FromName != td.ToName
}
func (td TableDelta) Type() string {
func (td TableDelta) TypeString() string {
if td.IsAdd() {
return "added"
}
if td.IsDrop() {
return "dropped"
}
if td.IsRename() {
return "renamed"
}
return "modified"
}
@@ -404,17 +407,78 @@ func (td TableDelta) IsKeyless(ctx context.Context) (bool, error) {
}
}
// isTableDataEmpty return true if the table does not contain any data
func isTableDataEmpty(ctx context.Context, table *doltdb.Table) (bool, error) {
rowData, err := table.GetRowData(ctx)
if err != nil {
return false, err
}
return rowData.Empty()
}
// GetSummary returns a summary of the table delta.
func (td TableDelta) GetSummary(ctx context.Context, dataChanged bool) (*TableDeltaSummary, error) {
func (td TableDelta) GetSummary(ctx context.Context) (*TableDeltaSummary, error) {
// Dropping a table is always a schema change, and also a data change if the table contained data
if td.IsDrop() {
isEmpty, err := isTableDataEmpty(ctx, td.FromTable)
if err != nil {
return nil, err
}
return &TableDeltaSummary{
TableName: td.FromName,
DataChange: !isEmpty,
SchemaChange: true,
DiffType: "dropped",
}, nil
}
// Renaming a table is always a schema change, and also a data change if the table data differs
if td.IsRename() {
dataChanged, err := td.HasHashChanged()
if err != nil {
return nil, err
}
return &TableDeltaSummary{
TableName: td.ToName,
DataChange: dataChanged,
SchemaChange: true,
DiffType: "renamed",
}, nil
}
// Creating a table is always a schema change, and also a data change if data was inserted
if td.IsAdd() {
isEmpty, err := isTableDataEmpty(ctx, td.ToTable)
if err != nil {
return nil, err
}
return &TableDeltaSummary{
TableName: td.ToName,
DataChange: !isEmpty,
SchemaChange: true,
DiffType: "added",
}, nil
}
dataChanged, err := td.HasHashChanged()
if err != nil {
return nil, err
}
schemaChanged, err := td.HasSchemaChanged(ctx)
if err != nil {
return nil, err
}
return &TableDeltaSummary{
HasSchemaChanges: schemaChanged,
HasDataChanges: dataChanged,
DiffType: td.Type(),
TableName: td.CurName(),
TableName: td.ToName,
DataChange: dataChanged,
SchemaChange: schemaChanged,
DiffType: "modified",
}, nil
}
@@ -241,20 +241,20 @@ func (d *doltDiffWorkingSetRowItr) Next(ctx *sql.Context) (sql.Row, error) {
return nil, io.EOF
}
change, err := processTableDelta(ctx, tableDelta)
change, err := tableDelta.GetSummary(ctx)
if err != nil {
return nil, err
}
sqlRow := sql.NewRow(
changeSet,
change.tableName,
change.TableName,
nil, // committer
nil, // email
nil, // date
nil, // message
change.dataChange,
change.schemaChange,
change.DataChange,
change.SchemaChange,
)
return sqlRow, nil
@@ -288,7 +288,7 @@ type doltDiffCommitHistoryRowItr struct {
commits []*doltdb.Commit
meta *datas.CommitMeta
hash hash.Hash
tableChanges []tableChange
tableChanges []diff.TableDeltaSummary
tableChangesIdx int
}
@@ -358,13 +358,13 @@ func (itr *doltDiffCommitHistoryRowItr) Next(ctx *sql.Context) (sql.Row, error)
return sql.NewRow(
h.String(),
tableChange.tableName,
tableChange.TableName,
meta.Name,
meta.Email,
meta.Time(),
meta.Description,
tableChange.dataChange,
tableChange.schemaChange,
tableChange.DataChange,
tableChange.SchemaChange,
), nil
}
@@ -399,7 +399,7 @@ func (itr *doltDiffCommitHistoryRowItr) loadTableChanges(ctx context.Context, co
// calculateTableChanges calculates the tables that changed in the specified commit, by comparing that
// commit with its immediate ancestor commit.
func (itr *doltDiffCommitHistoryRowItr) calculateTableChanges(ctx context.Context, commit *doltdb.Commit) ([]tableChange, error) {
func (itr *doltDiffCommitHistoryRowItr) calculateTableChanges(ctx context.Context, commit *doltdb.Commit) ([]diff.TableDeltaSummary, error) {
if len(commit.DatasParents()) == 0 {
return nil, nil
}
@@ -424,9 +424,9 @@ func (itr *doltDiffCommitHistoryRowItr) calculateTableChanges(ctx context.Contex
return nil, err
}
tableChanges := make([]tableChange, len(deltas))
tableChanges := make([]diff.TableDeltaSummary, len(deltas))
for i := 0; i < len(deltas); i++ {
change, err := processTableDelta(itr.ctx, deltas[i])
change, err := deltas[i].GetSummary(itr.ctx)
if err != nil {
return nil, err
}
@@ -442,68 +442,6 @@ func (itr *doltDiffCommitHistoryRowItr) calculateTableChanges(ctx context.Contex
return tableChanges, nil
}
// processTableDelta processes the specified TableDelta to determine what kind of change it was (i.e. table drop,
// table rename, table create, or data update) and returns a tableChange struct representing the change.
func processTableDelta(ctx *sql.Context, delta diff.TableDelta) (*tableChange, error) {
// Dropping a table is always a schema change, and also a data change if the table contained data
if delta.IsDrop() {
isEmpty, err := isTableDataEmpty(ctx, delta.FromTable)
if err != nil {
return nil, err
}
return &tableChange{
tableName: delta.FromName,
dataChange: !isEmpty,
schemaChange: true,
}, nil
}
// Renaming a table is always a schema change, and also a data change if the table data differs
if delta.IsRename() {
dataChanged, err := delta.HasHashChanged()
if err != nil {
return nil, err
}
return &tableChange{
tableName: delta.ToName,
dataChange: dataChanged,
schemaChange: true,
}, nil
}
// Creating a table is always a schema change, and also a data change if data was inserted
if delta.IsAdd() {
isEmpty, err := isTableDataEmpty(ctx, delta.ToTable)
if err != nil {
return nil, err
}
return &tableChange{
tableName: delta.ToName,
dataChange: !isEmpty,
schemaChange: true,
}, nil
}
dataChanged, err := delta.HasHashChanged()
if err != nil {
return nil, err
}
schemaChanged, err := delta.HasSchemaChanged(ctx)
if err != nil {
return nil, err
}
return &tableChange{
tableName: delta.ToName,
dataChange: dataChanged,
schemaChange: schemaChanged,
}, nil
}
// Close closes the iterator.
func (itr *doltDiffCommitHistoryRowItr) Close(*sql.Context) error {
return nil