diff --git a/go/vt/schemadiff/column.go b/go/vt/schemadiff/column.go index ae341776ccc..da2145f3ab0 100644 --- a/go/vt/schemadiff/column.go +++ b/go/vt/schemadiff/column.go @@ -104,7 +104,18 @@ func (c *ColumnDefinitionEntity) ColumnDiff( ) (*ModifyColumnDiff, error) { if c.IsTextual() || other.IsTextual() { // We will now denormalize the columns charset & collate as needed (if empty, populate from table.) - + // Normalizing _this_ column definition: + if c.columnDefinition.Type.Charset.Name != "" && c.columnDefinition.Type.Options.Collate == "" { + // Charset defined without collation. Assign the default collation for that charset. + collation := env.CollationEnv().DefaultCollationForCharset(c.columnDefinition.Type.Charset.Name) + if collation == collations.Unknown { + return nil, &UnknownColumnCharsetCollationError{Column: c.columnDefinition.Name.String(), Charset: t1cc.charset} + } + defer func() { + c.columnDefinition.Type.Options.Collate = "" + }() + c.columnDefinition.Type.Options.Collate = env.CollationEnv().LookupName(collation) + } if c.columnDefinition.Type.Charset.Name == "" && c.columnDefinition.Type.Options.Collate != "" { // Column has explicit collation but no charset. We can infer the charset from the collation. collationID := env.CollationEnv().LookupByName(c.columnDefinition.Type.Options.Collate) @@ -118,6 +129,7 @@ func (c *ColumnDefinitionEntity) ColumnDiff( c.columnDefinition.Type.Charset.Name = charset } if c.columnDefinition.Type.Charset.Name == "" { + // Still nothing? Assign the table's charset/collation. defer func() { c.columnDefinition.Type.Charset.Name = "" c.columnDefinition.Type.Options.Collate = "" @@ -137,6 +149,18 @@ func (c *ColumnDefinitionEntity) ColumnDiff( c.columnDefinition.Type.Options.Collate = env.CollationEnv().LookupName(collation) } } + // Normalizing _the other_ column definition: + if other.columnDefinition.Type.Charset.Name != "" && other.columnDefinition.Type.Options.Collate == "" { + // Charset defined without collation. Assign the default collation for that charset. + collation := env.CollationEnv().DefaultCollationForCharset(other.columnDefinition.Type.Charset.Name) + if collation == collations.Unknown { + return nil, &UnknownColumnCharsetCollationError{Column: other.columnDefinition.Name.String(), Charset: t2cc.charset} + } + defer func() { + other.columnDefinition.Type.Options.Collate = "" + }() + other.columnDefinition.Type.Options.Collate = env.CollationEnv().LookupName(collation) + } if other.columnDefinition.Type.Charset.Name == "" && other.columnDefinition.Type.Options.Collate != "" { // Column has explicit collation but no charset. We can infer the charset from the collation. collationID := env.CollationEnv().LookupByName(other.columnDefinition.Type.Options.Collate) @@ -151,6 +175,7 @@ func (c *ColumnDefinitionEntity) ColumnDiff( } if other.columnDefinition.Type.Charset.Name == "" { + // Still nothing? Assign the table's charset/collation. defer func() { other.columnDefinition.Type.Charset.Name = "" other.columnDefinition.Type.Options.Collate = "" diff --git a/go/vt/schemadiff/table_test.go b/go/vt/schemadiff/table_test.go index 09997057e16..1168f53f3b6 100644 --- a/go/vt/schemadiff/table_test.go +++ b/go/vt/schemadiff/table_test.go @@ -1896,6 +1896,36 @@ func TestCreateTableDiff(t *testing.T) { from: "create table t (id int primary key, v varchar(64) character set utf8mb3 collate utf8mb3_bin)", to: "create table t (id int primary key, v varchar(64) collate utf8mb3_bin)", }, + { + name: "ignore identical implicit ascii charset", + from: "create table t (id int primary key, v varchar(64) character set ascii collate ascii_general_ci)", + to: "create table t (id int primary key, v varchar(64) collate ascii_general_ci)", + }, + { + name: "ignore identical implicit collation", + from: "create table t (id int primary key, v varchar(64) character set utf8mb3 collate utf8mb3_general_ci)", + to: "create table t (id int primary key, v varchar(64) character set utf8mb3)", + }, + { + name: "ignore identical implicit collation, reverse", + from: "create table t (id int primary key, v varchar(64) character set utf8mb3)", + to: "create table t (id int primary key, v varchar(64) character set utf8mb3 collate utf8mb3_general_ci)", + }, + { + name: "implicit charset and implciit collation", + from: "create table t (id int primary key, v varchar(64) character set utf8mb3)", + to: "create table t (id int primary key, v varchar(64) collate utf8mb3_general_ci)", + }, + { + name: "ignore identical implicit ascii collation", + from: "create table t (id int primary key, v varchar(64) character set ascii collate ascii_general_ci)", + to: "create table t (id int primary key, v varchar(64) character set ascii)", + }, + { + name: "implicit charset and implciit collation, ascii", + from: "create table t (id int primary key, v varchar(64) collate ascii_general_ci)", + to: "create table t (id int primary key, v varchar(64) character set ascii)", + }, { name: "normalized unsigned attribute", from: "create table t1 (id int primary key)", @@ -2925,6 +2955,11 @@ func TestNormalize(t *testing.T) { from: "create table t (id int primary key, v varchar(255) charset utf8mb4 collate utf8mb4_german2_ci)", to: "CREATE TABLE `t` (\n\t`id` int,\n\t`v` varchar(255) COLLATE utf8mb4_german2_ci,\n\tPRIMARY KEY (`id`)\n)", }, + { + name: "ascii charset and collation", + from: "create table t (id int primary key, v varchar(255) charset ascii collate ascii_general_ci) charset utf8mb3 collate utf8_general_ci", + to: "CREATE TABLE `t` (\n\t`id` int,\n\t`v` varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci,\n\tPRIMARY KEY (`id`)\n) CHARSET utf8mb3,\n COLLATE utf8mb3_general_ci", + }, { name: "correct case table options for engine", from: "create table t (id int signed primary key) engine innodb",