go/doltcore/{merge,sqle}: populate description column for dolt_schema_conflicts table

This commit is contained in:
Andy Arthur
2023-04-25 15:29:59 -07:00
parent dc00e49072
commit 1bfe045d2f
3 changed files with 59 additions and 42 deletions
+23 -19
View File
@@ -38,18 +38,6 @@ const (
DeletedCheckCollision
)
// todo: link to docs explaining how to resolve schema conflicts.
func SchemaConflictErr(cc ...SchemaConflict) error {
var sb strings.Builder
sb.WriteString("merge aborted: schema conflict found for tables: \n")
for i := range cc {
sb.WriteRune('\t')
sb.WriteString(cc[i].TableName)
sb.WriteRune('\n')
}
return errors.New(sb.String())
}
type SchemaConflict struct {
TableName string
ColConflicts []ColConflict
@@ -63,21 +51,37 @@ func (sc SchemaConflict) Count() int {
return len(sc.ColConflicts) + len(sc.IdxConflicts) + len(sc.ChkConflicts)
}
// String implements fmt.Stringer. This method is used to
// display schema conflicts on schema conflict read paths.
func (sc SchemaConflict) String() string {
return strings.Join(sc.messages(), "\n")
}
// Error implements error. This error will be returned to the
// user if merge is configured to error upon schema conflicts.
// todo: link to docs explaining how to resolve schema conflicts.
func (sc SchemaConflict) Error() string {
template := "merge aborted: schema conflict found for table %s \n" +
" please resolve schema conflicts before merging: %s"
var b strings.Builder
b.WriteString("merge aborted: schema conflict found for table ")
b.WriteString(sc.TableName)
b.WriteString("\n please resolve schema conflicts before merging")
for _, m := range sc.messages() {
b.WriteString("\n\t")
b.WriteString(m)
}
return fmt.Sprintf(template, sc.TableName, b.String())
}
func (sc SchemaConflict) messages() (mm []string) {
for _, c := range sc.ColConflicts {
b.WriteString(fmt.Sprintf("\t%s\n", c.String()))
mm = append(mm, c.String())
}
for _, c := range sc.IdxConflicts {
b.WriteString(fmt.Sprintf("\t%s\n", c.String()))
mm = append(mm, c.String())
}
for _, c := range sc.ChkConflicts {
b.WriteString(fmt.Sprintf("\t%s\n", c.String()))
mm = append(mm, c.String())
}
return b.String()
return
}
type ColConflict struct {
@@ -24,9 +24,11 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/diff"
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
"github.com/dolthub/dolt/go/libraries/doltcore/merge"
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlutil"
noms "github.com/dolthub/dolt/go/store/types"
)
var _ sql.Table = (*SchemaConflictsTable)(nil)
@@ -148,8 +150,20 @@ type schemaConflict struct {
description string
}
func newSchemaConflict(ctx context.Context, table string, br *doltdb.RootValue, c doltdb.SchemaConflict) (schemaConflict, error) {
base, err := getCreateTableStatementFromRoot(ctx, table, br)
func newSchemaConflict(ctx context.Context, table string, baseRoot *doltdb.RootValue, c doltdb.SchemaConflict) (schemaConflict, error) {
bs, err := baseRoot.GetAllSchemas(ctx)
if err != nil {
return schemaConflict{}, err
}
baseSch := bs[table]
fkc, err := baseRoot.GetForeignKeyCollection(ctx)
if err != nil {
return schemaConflict{}, err
}
baseFKs, _ := fkc.KeysForTable(table)
base, err := getCreateTableStatement(table, baseSch, baseFKs, bs)
if err != nil {
return schemaConflict{}, err
}
@@ -164,30 +178,20 @@ func newSchemaConflict(ctx context.Context, table string, br *doltdb.RootValue,
return schemaConflict{}, err
}
desc, err := getSchemaConflictDescription(ctx, table, baseSch, c.ToSch, c.FromSch)
if err != nil {
return schemaConflict{}, err
}
return schemaConflict{
table: table,
baseSch: base,
ourSch: ours,
theirSch: theirs,
table: table,
baseSch: base,
ourSch: ours,
theirSch: theirs,
description: desc,
}, nil
}
func getCreateTableStatementFromRoot(ctx context.Context, table string, root *doltdb.RootValue) (string, error) {
schemas, err := root.GetAllSchemas(ctx)
if err != nil {
return "", err
}
sch := schemas[table]
fkc, err := root.GetForeignKeyCollection(ctx)
if err != nil {
return "", err
}
fks, _ := fkc.KeysForTable(table)
return getCreateTableStatement(table, sch, fks, schemas)
}
func getCreateTableStatement(table string, sch schema.Schema, fks []doltdb.ForeignKey, parents map[string]schema.Schema) (string, error) {
pkSch, err := sqlutil.FromDoltSchema(table, sch)
if err != nil {
@@ -196,6 +200,15 @@ func getCreateTableStatement(table string, sch schema.Schema, fks []doltdb.Forei
return diff.GenerateCreateTableStatement(table, sch, pkSch, fks, parents)
}
func getSchemaConflictDescription(ctx context.Context, table string, base, ours, theirs schema.Schema) (string, error) {
nbf := noms.Format_Default
_, conflict, err := merge.SchemaMerge(ctx, nbf, ours, theirs, base, table)
if err != nil {
return "", err
}
return conflict.String(), nil
}
type schemaConflictsIter struct {
conflicts []schemaConflict
baseSchemas map[string]schema.Schema
@@ -2906,7 +2906,7 @@ var SchemaConflictScripts = []queries.ScriptTest{
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `c0` varchar(20),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `c0` datetime(6),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `c0` int,\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
"",
"different column definitions for our column c0 and their column c0",
}},
},
{