mirror of
https://github.com/dolthub/dolt.git
synced 2026-05-20 19:38:55 -05:00
Merge pull request #5806 from dolthub/fulghum/schema-merge
Report schema conflicts for merges with column type changes
This commit is contained in:
@@ -92,7 +92,7 @@ type ColConflict struct {
|
||||
func (c ColConflict) String() string {
|
||||
switch c.Kind {
|
||||
case NameCollision:
|
||||
return fmt.Sprintf("two columns with the same name '%s' have different tags. See https://github.com/dolthub/dolt/issues/3963", c.Ours.Name)
|
||||
return fmt.Sprintf("incompatible column types for column '%s': %s and %s", c.Ours.Name, c.Ours.TypeInfo, c.Theirs.TypeInfo)
|
||||
case TagCollision:
|
||||
return fmt.Sprintf("different column definitions for our column %s and their column %s", c.Ours.Name, c.Theirs.Name)
|
||||
}
|
||||
@@ -152,7 +152,7 @@ func SchemaMerge(ctx context.Context, format *types.NomsBinFormat, ourSch, their
|
||||
}
|
||||
|
||||
var mergedCC *schema.ColCollection
|
||||
mergedCC, sc.ColConflicts, err = mergeColumns(ourSch.GetAllCols(), theirSch.GetAllCols(), ancSch.GetAllCols())
|
||||
mergedCC, sc.ColConflicts, err = mergeColumns(format, ourSch.GetAllCols(), theirSch.GetAllCols(), ancSch.GetAllCols())
|
||||
if err != nil {
|
||||
return nil, SchemaConflict{}, err
|
||||
}
|
||||
@@ -303,9 +303,11 @@ func ForeignKeysMerge(ctx context.Context, mergedRoot, ourRoot, theirRoot, ancRo
|
||||
// mergeColumns merges the columns from |ourCC|, |theirCC| into a single column collection, using the ancestor column
|
||||
// definitions in |ancCC| to determine on which side a column has changed. If merging is not possible because of
|
||||
// conflicting changes to the columns in |ourCC| and |theirCC|, then a set of ColConflict instances are returned
|
||||
// describing the conflicts. If any other, unexpected error occurs, then that error is returned and the other response
|
||||
// fields should be ignored.
|
||||
func mergeColumns(ourCC, theirCC, ancCC *schema.ColCollection) (*schema.ColCollection, []ColConflict, error) {
|
||||
// describing the conflicts. |format| indicates what storage format is in use, and is needed to determine compatibility
|
||||
// between types, since different storage formats have different restrictions on how much types can change and remain
|
||||
// compatible with the current stored format. If any unexpected error occurs, then that error is returned and the
|
||||
// other response fields should be ignored.
|
||||
func mergeColumns(format *types.NomsBinFormat, ourCC, theirCC, ancCC *schema.ColCollection) (*schema.ColCollection, []ColConflict, error) {
|
||||
columnMappings, err := mapColumns(ourCC, theirCC, ancCC)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -344,9 +346,25 @@ func mergeColumns(ourCC, theirCC, ancCC *schema.ColCollection) (*schema.ColColle
|
||||
if oursChanged && theirsChanged {
|
||||
// This is a schema change conflict and has already been handled by checkSchemaConflicts
|
||||
} else if theirsChanged {
|
||||
mergedColumns = append(mergedColumns, *theirs)
|
||||
if columnTypesAreCompatible(format, *ours, *theirs) {
|
||||
mergedColumns = append(mergedColumns, *theirs)
|
||||
} else {
|
||||
conflicts = append(conflicts, ColConflict{
|
||||
Kind: NameCollision,
|
||||
Ours: *ours,
|
||||
Theirs: *theirs,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
mergedColumns = append(mergedColumns, *ours)
|
||||
if columnTypesAreCompatible(format, *theirs, *ours) {
|
||||
mergedColumns = append(mergedColumns, *ours)
|
||||
} else {
|
||||
conflicts = append(conflicts, ColConflict{
|
||||
Kind: NameCollision,
|
||||
Ours: *ours,
|
||||
Theirs: *theirs,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if ours.Equals(*theirs) {
|
||||
// if the columns are identical, just use ours
|
||||
@@ -477,6 +495,34 @@ func checkSchemaConflicts(columnMappings columnMappings) ([]ColConflict, error)
|
||||
return conflicts, nil
|
||||
}
|
||||
|
||||
// columnTypesAreCompatible returns true if the change from |from| to |to| is a compatible type change.
|
||||
// Currently, no type change for the DOLT storage format is considered compatible, but over time we will
|
||||
// widen this to include safe type migrations (e.g. smallint to bigint, varchar(100) to varchar(200)), which
|
||||
// can require rewriting existing stored data to be compatible with the new type. For the older LD_1 storage
|
||||
// format, we are looser with type equality and consider them compatible as long as the types are in the
|
||||
// same type family/kind.
|
||||
func columnTypesAreCompatible(format *types.NomsBinFormat, from, to schema.Column) bool {
|
||||
if !from.TypeInfo.Equals(to.TypeInfo) {
|
||||
if types.IsFormat_DOLT(format) {
|
||||
// All type changes are incompatible, for the DOLT storage format.
|
||||
// TODO: this is overly broad, and should be narrowed down
|
||||
return false
|
||||
}
|
||||
|
||||
if from.Kind != to.Kind {
|
||||
return false
|
||||
}
|
||||
|
||||
if schema.IsColSpatialType(to) {
|
||||
// We need to do this because some spatial type changes require a full table check, but not all.
|
||||
// TODO: This could be narrowed down to a smaller set of spatial type changes
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// columnMapping describes the mapping for a column being merged between the two sides of the merge as well as the ancestor.
|
||||
type columnMapping struct {
|
||||
anc *schema.Column
|
||||
|
||||
@@ -3721,6 +3721,8 @@ var DoltVerifyConstraintsTestScripts = []queries.ScriptTest{
|
||||
var errTmplNoAutomaticMerge = "table %s can't be automatically merged.\nTo merge this table, make the schema on the source and target branch equal."
|
||||
|
||||
var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
|
||||
// Data conflicts during a merge with schema changes
|
||||
{
|
||||
Name: "data conflict",
|
||||
AncSetUpScript: []string{
|
||||
@@ -3760,51 +3762,8 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "unique constraint violation",
|
||||
AncSetUpScript: []string{
|
||||
"set autocommit = 0;",
|
||||
"CREATE table t (pk varchar(100) primary key, col1 int, col2 varchar(100), UNIQUE KEY unique1 (col2));",
|
||||
"INSERT into t values ('0', 0, '');",
|
||||
"alter table t add index idx1 (pk, col2);",
|
||||
},
|
||||
RightSetUpScript: []string{
|
||||
"alter table t drop column col1;",
|
||||
"INSERT into t (pk, col2) values ('10', 'same');",
|
||||
},
|
||||
LeftSetUpScript: []string{
|
||||
"INSERT into t values ('1', 10, 'same');",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "call dolt_merge('right');",
|
||||
Expected: []sql.Row{{0, 0x1}},
|
||||
},
|
||||
{
|
||||
Query: "select * from dolt_conflicts;",
|
||||
Expected: []sql.Row{},
|
||||
},
|
||||
{
|
||||
Query: "select * from dolt_constraint_violations;",
|
||||
Expected: []sql.Row{{"t", uint(2)}},
|
||||
},
|
||||
{
|
||||
Query: "select violation_type, pk, col2, violation_info from dolt_constraint_violations_t;",
|
||||
Expected: []sql.Row{
|
||||
{uint(2), "1", "same", types.JSONDocument{Val: merge.UniqCVMeta{Columns: []string{"col2"}, Name: "unique1"}}},
|
||||
{uint(2), "10", "same", types.JSONDocument{Val: merge.UniqCVMeta{Columns: []string{"col2"}, Name: "unique1"}}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "select pk, col2 from t;",
|
||||
Expected: []sql.Row{
|
||||
{"0", ""},
|
||||
{"1", "same"},
|
||||
{"10", "same"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Basic column changes – adds/drops/renames/reorders
|
||||
{
|
||||
Name: "dropping columns",
|
||||
AncSetUpScript: []string{
|
||||
@@ -3877,8 +3836,6 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
"alter table t add index idx4 (col1, col2);",
|
||||
"alter table t add index idx5 (col2, col1);",
|
||||
"alter table t add index idx6 (col2, pk, col1);",
|
||||
// TODO: This duplicate index causes a race condition in the merge code
|
||||
//"alter table t add index idx7 (col2);",
|
||||
},
|
||||
RightSetUpScript: []string{
|
||||
"alter table t rename column col1 to col11;",
|
||||
@@ -4034,6 +3991,8 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Constraint changes
|
||||
{
|
||||
Name: "removing a not-null constraint",
|
||||
AncSetUpScript: []string{
|
||||
@@ -4160,6 +4119,51 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "unique constraint violation",
|
||||
AncSetUpScript: []string{
|
||||
"set autocommit = 0;",
|
||||
"CREATE table t (pk varchar(100) primary key, col1 int, col2 varchar(100), UNIQUE KEY unique1 (col2));",
|
||||
"INSERT into t values ('0', 0, '');",
|
||||
"alter table t add index idx1 (pk, col2);",
|
||||
},
|
||||
RightSetUpScript: []string{
|
||||
"alter table t drop column col1;",
|
||||
"INSERT into t (pk, col2) values ('10', 'same');",
|
||||
},
|
||||
LeftSetUpScript: []string{
|
||||
"INSERT into t values ('1', 10, 'same');",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "call dolt_merge('right');",
|
||||
Expected: []sql.Row{{0, 0x1}},
|
||||
},
|
||||
{
|
||||
Query: "select * from dolt_conflicts;",
|
||||
Expected: []sql.Row{},
|
||||
},
|
||||
{
|
||||
Query: "select * from dolt_constraint_violations;",
|
||||
Expected: []sql.Row{{"t", uint(2)}},
|
||||
},
|
||||
{
|
||||
Query: "select violation_type, pk, col2, violation_info from dolt_constraint_violations_t;",
|
||||
Expected: []sql.Row{
|
||||
{uint(2), "1", "same", types.JSONDocument{Val: merge.UniqCVMeta{Columns: []string{"col2"}, Name: "unique1"}}},
|
||||
{uint(2), "10", "same", types.JSONDocument{Val: merge.UniqCVMeta{Columns: []string{"col2"}, Name: "unique1"}}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "select pk, col2 from t;",
|
||||
Expected: []sql.Row{
|
||||
{"0", ""},
|
||||
{"1", "same"},
|
||||
{"10", "same"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dropping a unique key",
|
||||
AncSetUpScript: []string{
|
||||
@@ -4187,7 +4191,85 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
},
|
||||
},
|
||||
|
||||
// Schema conflict test cases
|
||||
// Schema conflicts
|
||||
{
|
||||
// Type widening - these changes move from smaller types to bigger types, so they are guaranteed to be safe.
|
||||
// TODO: We don't support automatically converting column types in merges yet, so currently these won't
|
||||
// automatically merge and instead return schema conflicts.
|
||||
Name: "type widening",
|
||||
AncSetUpScript: []string{
|
||||
"CREATE table t (pk int primary key, col1 enum('blue', 'green'), col2 float, col3 smallint, " +
|
||||
"col4 decimal(4,2), col5 varchar(10), col6 set('a', 'b'), col7 bit(1));",
|
||||
"INSERT into t values (1, 'blue', 1.0, 1, 0.1, 'one', 'a,b', 1);",
|
||||
"alter table t add index idx1 (col1);",
|
||||
},
|
||||
RightSetUpScript: []string{
|
||||
"alter table t modify column col1 enum('blue', 'green', 'red');",
|
||||
"alter table t modify column col2 double;",
|
||||
"alter table t modify column col3 bigint;",
|
||||
"alter table t modify column col4 decimal(8,4);",
|
||||
"alter table t modify column col5 varchar(20);",
|
||||
"alter table t modify column col6 set('a', 'b', 'c');",
|
||||
"alter table t modify column col7 bit(2);",
|
||||
"INSERT into t values (3, 'red', 3.0, 420, 0.001, 'three', 'a,b,c', 3);",
|
||||
},
|
||||
LeftSetUpScript: []string{
|
||||
"INSERT into t values (2, 'green', 2.0, 2, 0.2, 'two', 'a,b', 1);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "call dolt_merge('right');",
|
||||
Expected: []sql.Row{{0, 0x1}},
|
||||
},
|
||||
{
|
||||
Query: "select table_name, our_schema, their_schema, base_schema from dolt_schema_conflicts;",
|
||||
Expected: []sql.Row{{"t",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` enum('blue','green'),\n `col2` float,\n `col3` smallint,\n `col4` decimal(4,2),\n `col5` varchar(10),\n `col6` set('a','b'),\n `col7` bit(1),\n PRIMARY KEY (`pk`),\n KEY `idx1` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` enum('blue','green','red'),\n `col2` double,\n `col3` bigint,\n `col4` decimal(8,4),\n `col5` varchar(20),\n `col6` set('a','b','c'),\n `col7` bit(2),\n PRIMARY KEY (`pk`),\n KEY `idx1` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` enum('blue','green'),\n `col2` float,\n `col3` smallint,\n `col4` decimal(4,2),\n `col5` varchar(10),\n `col6` set('a','b'),\n `col7` bit(1),\n PRIMARY KEY (`pk`),\n KEY `idx1` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// Type shortening – these changes move from a larger type to a smaller type and are not always safe.
|
||||
// For now, we automatically fail all of these with a schema conflict that the user must resolve, but in
|
||||
// theory, we could try to apply these changes and see if the data in the tables is compatible or not, but
|
||||
// that's an optimization left for the future. Until then, customers can manually alter their schema to
|
||||
// get merges to work, based on the schema conflict information.
|
||||
Name: "type shortening",
|
||||
AncSetUpScript: []string{
|
||||
"CREATE TABLE t (pk int primary key, col1 enum('blue','green','red'), col2 double, col3 bigint, col4 decimal(8,4), " +
|
||||
"col5 varchar(20), col6 set('a','b','c'), col7 bit(2));",
|
||||
"INSERT into t values (3, 'green', 3.0, 420, 0.001, 'three', 'a,b', 1);",
|
||||
"alter table t add index idx1 (col1);",
|
||||
},
|
||||
RightSetUpScript: []string{
|
||||
"alter table t modify column col1 enum('blue', 'green');",
|
||||
"alter table t modify column col2 float;",
|
||||
"alter table t modify column col3 smallint;",
|
||||
"alter table t modify column col4 decimal(4,2);",
|
||||
"alter table t modify column col5 varchar(10);",
|
||||
"alter table t modify column col6 set('a', 'b');",
|
||||
"alter table t modify column col7 bit(1);",
|
||||
"INSERT into t values (1, 'blue', 1.0, 1, 0.1, 'one', 'a,b', 1);",
|
||||
},
|
||||
LeftSetUpScript: []string{
|
||||
"INSERT into t values (2, 'green', 2.0, 2, 0.2, 'two', 'a,b', 1);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "call dolt_merge('right');",
|
||||
Expected: []sql.Row{{0, 0x1}},
|
||||
},
|
||||
{
|
||||
Query: "select table_name, our_schema, their_schema, base_schema from dolt_schema_conflicts;",
|
||||
Expected: []sql.Row{{"t",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` enum('blue','green','red'),\n `col2` double,\n `col3` bigint,\n `col4` decimal(8,4),\n `col5` varchar(20),\n `col6` set('a','b','c'),\n `col7` bit(2),\n PRIMARY KEY (`pk`),\n KEY `idx1` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` enum('blue','green'),\n `col2` float,\n `col3` smallint,\n `col4` decimal(4,2),\n `col5` varchar(10),\n `col6` set('a','b'),\n `col7` bit(1),\n PRIMARY KEY (`pk`),\n KEY `idx1` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` enum('blue','green','red'),\n `col2` double,\n `col3` bigint,\n `col4` decimal(8,4),\n `col5` varchar(20),\n `col6` set('a','b','c'),\n `col7` bit(2),\n PRIMARY KEY (`pk`),\n KEY `idx1` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "index conflicts: both sides add an index with the same name, same columns, but different type",
|
||||
AncSetUpScript: []string{
|
||||
@@ -4216,7 +4298,6 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
// https://github.com/dolthub/dolt/issues/2973
|
||||
Name: "modifying a column on one side of a merge, and deleting it on the other",
|
||||
@@ -4262,15 +4343,69 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Smarter merge conflict detection
|
||||
{
|
||||
// This merge tests reports a conflict on pk=1, because the tuple value is different on the left side, right
|
||||
Name: "changing the type of a column",
|
||||
AncSetUpScript: []string{
|
||||
"create table t (pk int primary key, col1 int);",
|
||||
"insert into t values (1, 10), (2, 20);",
|
||||
},
|
||||
RightSetUpScript: []string{
|
||||
"alter table t modify column col1 varchar(100)",
|
||||
"insert into t values (3, 'thirty'), (4, 'forty')",
|
||||
},
|
||||
LeftSetUpScript: []string{
|
||||
"insert into t values (5, 50), (6, 60);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "call dolt_merge('right');",
|
||||
Expected: []sql.Row{{0, 1}},
|
||||
},
|
||||
{
|
||||
Query: "select table_name, our_schema, their_schema, base_schema from dolt_schema_conflicts;",
|
||||
Expected: []sql.Row{{"t",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` int,\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` varchar(100),\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` int,\n PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "changing the type of a column with an index",
|
||||
AncSetUpScript: []string{
|
||||
"create table t (pk int primary key, col1 int, INDEX col1_idx (col1));",
|
||||
"insert into t values (1, 100), (2, 20);",
|
||||
},
|
||||
RightSetUpScript: []string{
|
||||
"alter table t modify column col1 varchar(100);",
|
||||
"insert into t values (3, 'thirty'), (4, 'forty')",
|
||||
},
|
||||
LeftSetUpScript: []string{
|
||||
"insert into t values (5, 50), (6, 60);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "call dolt_merge('right');",
|
||||
Expected: []sql.Row{{0, 1}},
|
||||
},
|
||||
{
|
||||
Query: "select table_name, our_schema, their_schema, base_schema from dolt_schema_conflicts;",
|
||||
Expected: []sql.Row{{"t",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` int,\n PRIMARY KEY (`pk`),\n KEY `col1_idx` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` varchar(100),\n PRIMARY KEY (`pk`),\n KEY `col1_idx` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` int,\n PRIMARY KEY (`pk`),\n KEY `col1_idx` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Unsupported automatic merge cases
|
||||
{
|
||||
// This merge test reports a conflict on pk=1, because the tuple value is different on the left side, right
|
||||
// side, and base. The value is the base is (10, '100'), on the right is nil, and on the left is ('100'),
|
||||
// because the data migration for the schema change happens before the diff iterator is invoked.
|
||||
// This should NOT be a conflict for a user – Dolt should not conflate the schema merge data migration with
|
||||
// a real data conflict created by a user. Allowing this is still better than completely blocking all schema
|
||||
// merges though, so we can live with this while we continue iterating and fine tuning schema merge logic.
|
||||
// merges though, so we can live with this while we continue iterating and fine-tuning schema merge logic.
|
||||
Name: "schema change combined with drop row",
|
||||
AncSetUpScript: []string{
|
||||
"SET autocommit = 0",
|
||||
@@ -4304,10 +4439,8 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Unsupported automatic merge cases
|
||||
{
|
||||
Name: "adding a non-null column to one side",
|
||||
Name: "adding a non-null column with a default value to one side",
|
||||
AncSetUpScript: []string{
|
||||
"create table t (pk int primary key, col1 int);",
|
||||
"insert into t values (1, 1);",
|
||||
@@ -4334,71 +4467,7 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "changing the type of a column",
|
||||
AncSetUpScript: []string{
|
||||
"create table t (pk int primary key, col1 int);",
|
||||
"insert into t values (1, 10), (2, 20);",
|
||||
},
|
||||
RightSetUpScript: []string{
|
||||
"alter table t modify column col1 varchar(100)",
|
||||
"insert into t values (3, 'thirty'), (4, 'forty')",
|
||||
},
|
||||
LeftSetUpScript: []string{
|
||||
"insert into t values (5, 50), (6, 60);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "call dolt_merge('right');",
|
||||
ExpectedErrStr: fmt.Sprintf(errTmplNoAutomaticMerge, "t"),
|
||||
},
|
||||
{
|
||||
Query: "select pk, col1 from t;",
|
||||
Expected: []sql.Row{
|
||||
{1, "10"},
|
||||
{2, "20"},
|
||||
{3, "thirty"},
|
||||
{4, "forty"},
|
||||
{5, "50"},
|
||||
{6, "60"},
|
||||
},
|
||||
Skip: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "changing the type of a column with an index",
|
||||
AncSetUpScript: []string{
|
||||
"create table t (pk int primary key, col1 int, INDEX col1_idx (col1));",
|
||||
"insert into t values (1, 100), (2, 20);",
|
||||
},
|
||||
RightSetUpScript: []string{
|
||||
"alter table t modify column col1 varchar(100);",
|
||||
"insert into t values (3, 'thirty'), (4, 'forty')",
|
||||
},
|
||||
LeftSetUpScript: []string{
|
||||
"insert into t values (5, 50), (6, 60);",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "call dolt_merge('right');",
|
||||
ExpectedErrStr: fmt.Sprintf(errTmplNoAutomaticMerge, "t"),
|
||||
},
|
||||
{
|
||||
Skip: true,
|
||||
Query: "select pk, col1 from t order by col1;",
|
||||
Expected: []sql.Row{
|
||||
{1, "100"},
|
||||
{2, "20"},
|
||||
{3, "thirty"},
|
||||
{4, "forty"},
|
||||
{5, "50"},
|
||||
{6, "60"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "adding a not-null constraint with default to a column",
|
||||
Name: "adding a not-null constraint and default value to a column",
|
||||
AncSetUpScript: []string{
|
||||
"create table t (pk int primary key, col1 int);",
|
||||
"insert into t values (1, null), (2, null);",
|
||||
@@ -4451,9 +4520,9 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
},
|
||||
},
|
||||
{
|
||||
// It would make sense if we table-scanned for check constraints during merge
|
||||
// and flagged failing constraints as violations in `dolt_constraint_violations`.
|
||||
Name: "adding a check-constraint should abort the merge.",
|
||||
// TODO: We should scan for check constraints during merge and flag failing
|
||||
// constraints as violations in `dolt_constraint_violations`.
|
||||
Name: "adding a check-constraint",
|
||||
AncSetUpScript: []string{
|
||||
"create table t (pk int primary key, col1 int);",
|
||||
"insert into t values (1, 1);",
|
||||
@@ -4467,14 +4536,18 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Skip: true,
|
||||
Query: "call dolt_merge('right');",
|
||||
ExpectedErrStr: "some schema error",
|
||||
// TODO: Dolt currently merges this without an error, but it shouldn't;
|
||||
// There is a constraint violation that should be reported.
|
||||
Skip: true,
|
||||
Query: "call dolt_merge('right');",
|
||||
Expected: []sql.Row{{0, 0x1}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "changing the collation of an indexed column is broken",
|
||||
// TODO: Changing a column's collation requires rewriting the table and any indexes containing that column.
|
||||
// For now, we just detect the schema incompatibility and return schema conflict metadata.
|
||||
Name: "changing the collation of an indexed column",
|
||||
AncSetUpScript: []string{
|
||||
"create table t (pk int primary key, col1 varchar(32) character set utf8mb4 collate utf8mb4_bin, index col1_idx (col1));",
|
||||
"insert into t values (1, 'ab'), (2, 'Ab');",
|
||||
@@ -4486,10 +4559,16 @@ var ThreeWayMergeWithSchemaChangeTestScripts = []MergeScriptTest{
|
||||
"insert into t values (3, 'c');",
|
||||
},
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
// TODO: Fails secondary index validation. Changing the ordinal ordering of secondary indexes definitely breaks merge
|
||||
{
|
||||
Query: "call dolt_merge('right');",
|
||||
ExpectedErrStr: fmt.Sprintf(errTmplNoAutomaticMerge, "t"),
|
||||
Query: "call dolt_merge('right');",
|
||||
Expected: []sql.Row{{0, 1}},
|
||||
},
|
||||
{
|
||||
Query: "select table_name, our_schema, their_schema, base_schema from dolt_schema_conflicts;",
|
||||
Expected: []sql.Row{{"t",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` varchar(32) COLLATE utf8mb4_bin,\n PRIMARY KEY (`pk`),\n KEY `col1_idx` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` varchar(32) COLLATE utf8mb4_general_ci,\n PRIMARY KEY (`pk`),\n KEY `col1_idx` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
|
||||
"CREATE TABLE `t` (\n `pk` int NOT NULL,\n `col1` varchar(32) COLLATE utf8mb4_bin,\n PRIMARY KEY (`pk`),\n KEY `col1_idx` (`col1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user