mirror of
https://github.com/ent/ent.git
synced 2026-05-24 09:31:56 +03:00
dialect/sql/schema: handle index prefix key limit in older versions of mariadb
Fixed #1378
This commit is contained in:
committed by
Ariel Mashraki
parent
56a0cf1e8b
commit
305edd00e0
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 != "" {
|
||||
|
||||
Reference in New Issue
Block a user