diff --git a/dialect/sql/schema/mysql.go b/dialect/sql/schema/mysql.go index a524f90e5..738dcd8ac 100644 --- a/dialect/sql/schema/mysql.go +++ b/dialect/sql/schema/mysql.go @@ -244,7 +244,7 @@ func (d *MySQL) cType(c *Column) (t string) { case field.TypeString: size := c.Size if size == 0 { - size = c.defaultSize(d.version) + size = d.defaultSize(c) } if size <= math.MaxUint16 { t = fmt.Sprintf("varchar(%d)", size) @@ -659,3 +659,24 @@ func (d *MySQL) fkNames(ctx context.Context, tx dialect.Tx, table, column string } return names, nil } + +// defaultSize returns the default size for MySQL/MariaDB varchar type +// based on column size, charset and table indexes, in order to avoid +// index prefix key limit (767) for older versions of MySQL/MariaDB. +func (d *MySQL) defaultSize(c *Column) int64 { + size := DefaultStringLen + version, checked := d.version, "5.7.0" + if v, ok := d.mariadb(); ok { + version, checked = v, "10.2.2" + } + switch { + // Version is >= 5.7 for MySQL, or >= 10.2.2 for MariaDB. + case compareVersions(version, checked) != -1: + // Column is non-unique, or not part of any index (reaching + // the error 1071). + case !c.Unique && len(c.indexes) == 0: + default: + size = 191 + } + return size +} diff --git a/dialect/sql/schema/mysql_test.go b/dialect/sql/schema/mysql_test.go index 7fa97c6b7..5a7bc2bfe 100644 --- a/dialect/sql/schema/mysql_test.go +++ b/dialect/sql/schema/mysql_test.go @@ -1143,6 +1143,40 @@ func TestMySQL_Create(t *testing.T) { mock.ExpectCommit() }, }, + { + name: "mariadb/10.1.37/create table", + tables: []*Table{ + { + Name: "users", + PrimaryKey: []*Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + }, + Columns: []*Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "age", Type: field.TypeInt}, + {Name: "name", Type: field.TypeString, Unique: true}, + }, + }, + }, + options: []MigrateOption{WithGlobalUniqueID(true)}, + before: func(mock mysqlMock) { + mock.start("10.1.48-MariaDB-1~bionic") + mock.tableExists("ent_types", false) + // create ent_types table. + mock.ExpectExec(escape("CREATE TABLE IF NOT EXISTS `ent_types`(`id` bigint unsigned AUTO_INCREMENT NOT NULL, `type` varchar(191) UNIQUE NOT NULL, PRIMARY KEY(`id`)) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin")). + WillReturnResult(sqlmock.NewResult(0, 1)) + mock.tableExists("users", false) + mock.ExpectExec(escape("CREATE TABLE IF NOT EXISTS `users`(`id` bigint AUTO_INCREMENT NOT NULL, `age` bigint NOT NULL, `name` varchar(191) UNIQUE NOT NULL, PRIMARY KEY(`id`)) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin")). + WillReturnResult(sqlmock.NewResult(0, 1)) + // set users id range. + mock.ExpectExec(escape("INSERT INTO `ent_types` (`type`) VALUES (?)")). + WithArgs("users"). + WillReturnResult(sqlmock.NewResult(0, 1)) + mock.ExpectExec(escape("ALTER TABLE `users` AUTO_INCREMENT = 0")). + WillReturnResult(sqlmock.NewResult(0, 1)) + mock.ExpectCommit() + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/dialect/sql/schema/schema.go b/dialect/sql/schema/schema.go index 9901e9acb..1f5c5b422 100644 --- a/dialect/sql/schema/schema.go +++ b/dialect/sql/schema/schema.go @@ -318,22 +318,6 @@ func (c *Column) nullable(b *sql.ColumnBuilder) { b.Attr(attr) } -// defaultSize returns the default size for MySQL varchar type based -// on column size, charset and table indexes, in order to avoid index -// prefix key limit (767). -func (c *Column) defaultSize(version string) int64 { - size := DefaultStringLen - switch { - // version is >= 5.7. - case compareVersions(version, "5.7.0") != -1: - // non-unique, or not part of any index (reaching the error 1071). - case !c.Unique && len(c.indexes) == 0: - default: - size = 191 - } - return size -} - // scanTypeOr returns the scanning type or the given value. func (c *Column) scanTypeOr(t string) string { if c.typ != "" {