diff --git a/dialect/sql/schema/migrate.go b/dialect/sql/schema/migrate.go index f4e17d4e1..2e9d5c06f 100644 --- a/dialect/sql/schema/migrate.go +++ b/dialect/sql/schema/migrate.go @@ -103,6 +103,7 @@ func (m *Migrate) Create(ctx context.Context, tables ...*Table) error { func (m *Migrate) create(ctx context.Context, tx dialect.Tx, tables ...*Table) error { for _, t := range tables { + t.linkColumns() switch exist, err := m.tableExist(ctx, tx, t.Name); { case err != nil: return err diff --git a/dialect/sql/schema/mysql.go b/dialect/sql/schema/mysql.go index d528de357..ac5acffaa 100644 --- a/dialect/sql/schema/mysql.go +++ b/dialect/sql/schema/mysql.go @@ -55,7 +55,7 @@ func (d *MySQL) table(ctx context.Context, tx dialect.Tx, name string) (*Table, } // call `Close` in cases of failures (`Close` is idempotent). defer rows.Close() - t := &Table{Name: name} + t := NewTable(name) for rows.Next() { c := &Column{} if err := c.ScanMySQL(rows); err != nil { @@ -64,7 +64,7 @@ func (d *MySQL) table(ctx context.Context, tx dialect.Tx, name string) (*Table, if c.PrimaryKey() { t.PrimaryKey = append(t.PrimaryKey, c) } - t.Columns = append(t.Columns, c) + t.AddColumn(c) } if err := rows.Close(); err != nil { return nil, fmt.Errorf("mysql: closing rows %v", err) @@ -73,7 +73,10 @@ func (d *MySQL) table(ctx context.Context, tx dialect.Tx, name string) (*Table, if err != nil { return nil, err } - t.Indexes = indexes + // add and link indexes to table columns. + for _, idx := range indexes { + t.AddIndex(idx.Name, idx.Unique, idx.columns) + } return t, nil } diff --git a/dialect/sql/schema/schema.go b/dialect/sql/schema/schema.go index bcc281e0a..ddc338280 100644 --- a/dialect/sql/schema/schema.go +++ b/dialect/sql/schema/schema.go @@ -62,12 +62,22 @@ func (t *Table) AddIndex(name string, unique bool, columns []string) *Table { c, ok := t.columns[name] if ok { idx.Columns[i] = c + c.indexes = append(c.indexes, idx) } } t.Indexes = append(t.Indexes, idx) return t } +// linkColumns links the table columns to their indexes for later referencing. +func (t *Table) linkColumns() { + for _, idx := range t.Indexes { + for _, c := range idx.Columns { + c.indexes.append(idx) + } + } +} + // MySQL returns the MySQL DSL query for table creation. func (t *Table) MySQL(version string) *sql.TableBuilder { b := sql.CreateTable(t.Name).IfNotExists() @@ -148,6 +158,7 @@ type Column struct { Default string // default value. Charset string // column character set. Collation string // column collation. + indexes Indexes // linked indexes. } // UniqueKey returns boolean indicates if this column is a unique key. @@ -372,18 +383,23 @@ func (c *Column) nullable(b *sql.ColumnBuilder) { } } -// defaultSize returns the default size for MySQL varchar -// type based on column size, charset and table indexes. +// 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) int { + size := DefaultStringLen parts := strings.Split(version, ".") - // non-unique or invalid version. - if !c.Unique || len(parts) == 1 || parts[0] == "" || parts[1] == "" { - return DefaultStringLen + switch { + // invalid version. + case len(parts) == 1 || parts[0] == "" || parts[1] == "": + // version is > 5.6.*. + case parts[0] > "5" || parts[1] > "6": + // non-unique, or not part of any index (reaching the error 1071). + case !c.Unique && len(c.indexes) == 0: + default: + size = 191 } - if major, minor := parts[0], parts[1]; major > "5" || minor > "6" { - return DefaultStringLen - } - return 191 + return size } // ForeignKey definition for creation. diff --git a/entc/integration/compose/docker-compose.yaml b/entc/integration/compose/docker-compose.yaml index 3fcf3336a..9d11790a3 100644 --- a/entc/integration/compose/docker-compose.yaml +++ b/entc/integration/compose/docker-compose.yaml @@ -3,7 +3,7 @@ version: "3.7" services: mysql: - image: mysql:5.7.23 + image: mysql:5.6.35 environment: MYSQL_DATABASE: test MYSQL_ROOT_PASSWORD: pass