mirror of
https://github.com/ent/ent.git
synced 2026-05-24 09:31:56 +03:00
dialect/sql/schema: add support for index prefixes in mysql
This commit is contained in:
committed by
Ariel Mashraki
parent
110073c982
commit
66871c9806
@@ -158,3 +158,100 @@ const (
|
||||
SetNull ReferenceOption = "SET NULL"
|
||||
SetDefault ReferenceOption = "SET DEFAULT"
|
||||
)
|
||||
|
||||
// IndexAnnotation is a builtin schema annotation for attaching
|
||||
// SQL metadata to schema indexes for both codegen and runtime.
|
||||
type IndexAnnotation struct {
|
||||
// Prefix defines a column prefix for a single string column index.
|
||||
// In MySQL, the following annotation maps to:
|
||||
//
|
||||
// index.Fields("column").
|
||||
// Annotation(entsql.Prefix(100))
|
||||
//
|
||||
// CREATE INDEX `table_column` ON `table`(`column`(100))
|
||||
//
|
||||
Prefix uint
|
||||
|
||||
// PrefixColumns defines column prefixes for a multi column index.
|
||||
// In MySQL, the following annotation maps to:
|
||||
//
|
||||
// index.Fields("c1", "c2", "c3").
|
||||
// Annotation(
|
||||
// entsql.PrefixColumn("c1", 100),
|
||||
// entsql.PrefixColumn("c2", 200),
|
||||
// )
|
||||
//
|
||||
// CREATE INDEX `table_c1_c2_c3` ON `table`(`c1`(100), `c2`(200), `c3`)
|
||||
//
|
||||
PrefixColumns map[string]uint
|
||||
}
|
||||
|
||||
// Prefix returns a new index annotation with a single string column index.
|
||||
// In MySQL, the following annotation maps to:
|
||||
//
|
||||
// index.Fields("column").
|
||||
// Annotation(entsql.Prefix(100))
|
||||
//
|
||||
// CREATE INDEX `table_column` ON `table`(`column`(100))
|
||||
//
|
||||
func Prefix(prefix uint) *IndexAnnotation {
|
||||
return &IndexAnnotation{
|
||||
Prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
// PrefixColumns returns a new index annotation with column prefix for
|
||||
// multi-column indexes. In MySQL, the following annotation maps to:
|
||||
//
|
||||
// index.Fields("c1", "c2", "c3").
|
||||
// Annotation(
|
||||
// entsql.PrefixColumn("c1", 100),
|
||||
// entsql.PrefixColumn("c2", 200),
|
||||
// )
|
||||
//
|
||||
// CREATE INDEX `table_c1_c2_c3` ON `table`(`c1`(100), `c2`(200), `c3`)
|
||||
//
|
||||
func PrefixColumn(name string, prefix uint) *IndexAnnotation {
|
||||
return &IndexAnnotation{
|
||||
PrefixColumns: map[string]uint{
|
||||
name: prefix,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Name describes the annotation name.
|
||||
func (IndexAnnotation) Name() string {
|
||||
return "EntSQLIndexes"
|
||||
}
|
||||
|
||||
// Merge implements the schema.Merger interface.
|
||||
func (a IndexAnnotation) Merge(other schema.Annotation) schema.Annotation {
|
||||
var ant IndexAnnotation
|
||||
switch other := other.(type) {
|
||||
case IndexAnnotation:
|
||||
ant = other
|
||||
case *IndexAnnotation:
|
||||
if other != nil {
|
||||
ant = *other
|
||||
}
|
||||
default:
|
||||
return a
|
||||
}
|
||||
if ant.Prefix != 0 {
|
||||
a.Prefix = ant.Prefix
|
||||
}
|
||||
if ant.PrefixColumns != nil {
|
||||
if a.PrefixColumns == nil {
|
||||
a.PrefixColumns = make(map[string]uint)
|
||||
}
|
||||
for column, prefix := range ant.PrefixColumns {
|
||||
a.PrefixColumns[column] = prefix
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
var (
|
||||
_ schema.Annotation = (*IndexAnnotation)(nil)
|
||||
_ schema.Merger = (*IndexAnnotation)(nil)
|
||||
)
|
||||
|
||||
@@ -67,37 +67,37 @@ func TestInspector_Tables(t *testing.T) {
|
||||
AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "").
|
||||
AddRow("text", "longtext", "YES", "YES", "NULL", "", "", "").
|
||||
AddRow("uuid", "char(36)", "YES", "YES", "NULL", "", "", "utf8mb4_bin"))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("public", "users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?")).
|
||||
WithArgs("public", "pets").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "").
|
||||
AddRow("user_pets", "bigint(20)", "YES", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("public", "pets").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?")).
|
||||
WithArgs("public", "groups").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("public", "groups").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?")).
|
||||
WithArgs("public", "user_groups").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("user_id", "bigint(20)", "NO", "YES", "NULL", "", "", "").
|
||||
AddRow("group_id", "bigint(20)", "NO", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("public", "user_groups").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}))
|
||||
},
|
||||
dialect.SQLite: func(mock mysqlMock) {
|
||||
mock.ExpectQuery(escape("SELECT `name` FROM `sqlite_schema` WHERE `type` = ?")).
|
||||
|
||||
@@ -385,6 +385,13 @@ func (m *Migrate) changeSet(curr, new *Table) (*changes, error) {
|
||||
case idx1.Unique != idx2.Unique:
|
||||
change.index.drop.append(idx2)
|
||||
change.index.add.append(idx1)
|
||||
default:
|
||||
im, ok := m.sqlDialect.(interface{ indexModified(old, new *Index) bool })
|
||||
// If the dialect supports comparing indexes.
|
||||
if ok && im.indexModified(idx2, idx1) {
|
||||
change.index.drop.append(idx2)
|
||||
change.index.add.append(idx1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/schema/field"
|
||||
)
|
||||
@@ -100,7 +101,7 @@ func (d *MySQL) table(ctx context.Context, tx dialect.Tx, name string) (*Table,
|
||||
}
|
||||
// Add and link indexes to table columns.
|
||||
for _, idx := range indexes {
|
||||
t.AddIndex(idx.Name, idx.Unique, idx.columns)
|
||||
t.addIndex(idx)
|
||||
}
|
||||
if _, ok := d.mariadb(); ok {
|
||||
if err := d.normalizeJSON(ctx, tx, t); err != nil {
|
||||
@@ -113,7 +114,7 @@ func (d *MySQL) table(ctx context.Context, tx dialect.Tx, name string) (*Table,
|
||||
// table loads the table indexes from the database.
|
||||
func (d *MySQL) indexes(ctx context.Context, tx dialect.Tx, name string) ([]*Index, error) {
|
||||
rows := &sql.Rows{}
|
||||
query, args := sql.Select("index_name", "column_name", "non_unique", "seq_in_index").
|
||||
query, args := sql.Select("index_name", "column_name", "sub_part", "non_unique", "seq_in_index").
|
||||
From(sql.Table("STATISTICS").Schema("INFORMATION_SCHEMA")).
|
||||
Where(sql.And(
|
||||
d.matchSchema(),
|
||||
@@ -303,7 +304,20 @@ func (d *MySQL) addColumn(c *Column) *sql.ColumnBuilder {
|
||||
|
||||
// addIndex returns the querying for adding an index to MySQL.
|
||||
func (d *MySQL) addIndex(i *Index, table string) *sql.IndexBuilder {
|
||||
return i.Builder(table)
|
||||
idx := sql.CreateIndex(i.Name).Table(table)
|
||||
if i.Unique {
|
||||
idx.Unique()
|
||||
}
|
||||
parts := indexParts(i)
|
||||
for _, c := range i.Columns {
|
||||
part, ok := parts[c.Name]
|
||||
if !ok || part == 0 {
|
||||
idx.Column(c.Name)
|
||||
} else {
|
||||
idx.Column(fmt.Sprintf("%s(%d)", idx.Builder.Quote(c.Name), part))
|
||||
}
|
||||
}
|
||||
return idx
|
||||
}
|
||||
|
||||
// dropIndex drops a MySQL index.
|
||||
@@ -460,8 +474,8 @@ func (d *MySQL) scanColumn(c *Column, rows *sql.Rows) error {
|
||||
}
|
||||
|
||||
// scanIndexes scans sql.Rows into an Indexes list. The query for returning the rows,
|
||||
// should return the following 4 columns: INDEX_NAME, COLUMN_NAME, NON_UNIQUE, SEQ_IN_INDEX.
|
||||
// SEQ_IN_INDEX specifies the position of the column in the index columns.
|
||||
// should return the following 5 columns: INDEX_NAME, COLUMN_NAME, SUB_PART, NON_UNIQUE,
|
||||
// SEQ_IN_INDEX. SEQ_IN_INDEX specifies the position of the column in the index columns.
|
||||
func (d *MySQL) scanIndexes(rows *sql.Rows) (Indexes, error) {
|
||||
var (
|
||||
i Indexes
|
||||
@@ -473,8 +487,9 @@ func (d *MySQL) scanIndexes(rows *sql.Rows) (Indexes, error) {
|
||||
column string
|
||||
nonuniq bool
|
||||
seqindex int
|
||||
subpart sql.NullInt64
|
||||
)
|
||||
if err := rows.Scan(&name, &column, &nonuniq, &seqindex); err != nil {
|
||||
if err := rows.Scan(&name, &column, &subpart, &nonuniq, &seqindex); err != nil {
|
||||
return nil, fmt.Errorf("scanning index description: %w", err)
|
||||
}
|
||||
// Ignore primary keys.
|
||||
@@ -483,11 +498,17 @@ func (d *MySQL) scanIndexes(rows *sql.Rows) (Indexes, error) {
|
||||
}
|
||||
idx, ok := names[name]
|
||||
if !ok {
|
||||
idx = &Index{Name: name, Unique: !nonuniq}
|
||||
idx = &Index{Name: name, Unique: !nonuniq, Annotation: &entsql.IndexAnnotation{}}
|
||||
i = append(i, idx)
|
||||
names[name] = idx
|
||||
}
|
||||
idx.columns = append(idx.columns, column)
|
||||
if subpart.Int64 > 0 {
|
||||
if idx.Annotation.PrefixColumns == nil {
|
||||
idx.Annotation.PrefixColumns = make(map[string]uint)
|
||||
}
|
||||
idx.Annotation.PrefixColumns[column] = uint(subpart.Int64)
|
||||
}
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
@@ -689,3 +710,35 @@ func (d *MySQL) defaultSize(c *Column) int64 {
|
||||
func (d *MySQL) needsConversion(old, new *Column) bool {
|
||||
return d.cType(old) != d.cType(new)
|
||||
}
|
||||
|
||||
// indexModified used by the migration differ to check if the index was modified.
|
||||
func (d *MySQL) indexModified(old, new *Index) bool {
|
||||
oldParts, newParts := indexParts(old), indexParts(new)
|
||||
if len(oldParts) != len(newParts) {
|
||||
return true
|
||||
}
|
||||
for column, oldPart := range oldParts {
|
||||
newPart, ok := newParts[column]
|
||||
if !ok || oldPart != newPart {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// indexParts returns a map holding the sub_part mapping if exist.
|
||||
func indexParts(idx *Index) map[string]uint {
|
||||
parts := make(map[string]uint)
|
||||
if idx.Annotation == nil {
|
||||
return parts
|
||||
}
|
||||
// If prefix (without a name) was defined on the
|
||||
// annotation, map it to the single column index.
|
||||
if idx.Annotation.Prefix > 0 && len(idx.Columns) == 1 {
|
||||
parts[idx.Columns[0].Name] = idx.Annotation.Prefix
|
||||
}
|
||||
for column, part := range idx.Annotation.PrefixColumns {
|
||||
parts[column] = part
|
||||
}
|
||||
return parts
|
||||
}
|
||||
|
||||
@@ -286,10 +286,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
AddRow("decimal", "decimal(6,2)", "NO", "YES", "NULL", "", "", "").
|
||||
AddRow("unsigned_decimal", "decimal(6,2) unsigned", "NO", "YES", "NULL", "", "", "").
|
||||
AddRow("timestamp", "timestamp", "NO", "NO", "CURRENT_TIMESTAMP", "DEFAULT_GENERATED on update CURRENT_TIMESTAMP", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` ADD COLUMN `age` bigint NOT NULL, ADD COLUMN `ts` timestamp NOT NULL")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -321,10 +321,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "").
|
||||
AddRow("enums1", "enum('a')", "YES", "NO", "NULL", "", "", "").
|
||||
AddRow("enums2", "enum('b', 'a')", "NO", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` MODIFY COLUMN `enums1` enum('a', 'b') NOT NULL, MODIFY COLUMN `enums2` enum('a') NOT NULL")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -356,10 +356,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
AddRow("created_at", "datetime", "NO", "YES", "NULL", "", "", "").
|
||||
AddRow("updated_at", "timestamp", "NO", "YES", "NULL", "", "", "").
|
||||
AddRow("deleted_at", "datetime", "NO", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` MODIFY COLUMN `updated_at` datetime NULL, MODIFY COLUMN `deleted_at` timestamp NULL")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -390,10 +390,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "").
|
||||
AddRow("doc", "longblob", "YES", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` ADD COLUMN `age` bigint NOT NULL DEFAULT 10")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -423,10 +423,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` ADD COLUMN `tiny` tinyblob NOT NULL, ADD COLUMN `blob` blob NOT NULL, ADD COLUMN `medium` mediumblob NOT NULL, ADD COLUMN `long` longblob NOT NULL")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -453,10 +453,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` ADD COLUMN `binary` binary(20) NOT NULL")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -486,10 +486,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("tiny", "varbinary(255)", "NO", "YES", "NULL", "", "", "").
|
||||
AddRow("medium", "varbinary(255)", "NO", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` MODIFY COLUMN `medium` longblob NOT NULL")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -518,10 +518,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec("ALTER TABLE `users` ADD COLUMN `age` double NOT NULL DEFAULT 10.1").
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -550,10 +550,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec("ALTER TABLE `users` ADD COLUMN `age` boolean NOT NULL DEFAULT true").
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -582,10 +582,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` ADD COLUMN `nick` varchar(255) NOT NULL DEFAULT 'unknown'")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -614,10 +614,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` ADD COLUMN `nick` longtext NOT NULL")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -645,10 +645,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` DROP COLUMN `name`")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -678,10 +678,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", "").
|
||||
AddRow("age", "bigint(20)", "NO", "NO", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` MODIFY COLUMN `name` varchar(255) NULL")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
@@ -709,10 +709,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("age", "bigint(20)", "NO", "", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
// create the unique index.
|
||||
mock.ExpectExec(escape("CREATE UNIQUE INDEX `age` ON `users`(`age`)")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
@@ -741,11 +741,11 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("age", "bigint(20)", "NO", "UNI", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1").
|
||||
AddRow("age", "age", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1").
|
||||
AddRow("age", "age", nil, "0", "1"))
|
||||
mock.ExpectCommit()
|
||||
},
|
||||
},
|
||||
@@ -772,11 +772,11 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("age", "bigint(20)", "NO", "UNI", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1").
|
||||
AddRow("age", "age", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1").
|
||||
AddRow("age", "age", nil, "0", "1"))
|
||||
// check if a foreign-key needs to be dropped.
|
||||
mock.ExpectQuery(escape("SELECT `CONSTRAINT_NAME` FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` WHERE `TABLE_NAME` = ? AND `COLUMN_NAME` = ? AND `POSITION_IN_UNIQUE_CONSTRAINT` IS NOT NULL AND `TABLE_SCHEMA` = (SELECT DATABASE())")).
|
||||
WithArgs("users", "age").
|
||||
@@ -787,6 +787,50 @@ func TestMySQL_Create(t *testing.T) {
|
||||
mock.ExpectCommit()
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "increase index sub_part",
|
||||
tables: func() []*Table {
|
||||
t := &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", Type: field.TypeInt, Increment: true},
|
||||
{Name: "text", Type: field.TypeString, Size: math.MaxInt32, Nullable: true},
|
||||
},
|
||||
PrimaryKey: []*Column{
|
||||
{Name: "id", Type: field.TypeInt, Increment: true},
|
||||
},
|
||||
Indexes: []*Index{
|
||||
{Name: "prefix_text", Annotation: &entsql.IndexAnnotation{Prefix: 100}},
|
||||
},
|
||||
}
|
||||
t.Indexes[0].Columns = t.Columns[1:]
|
||||
return []*Table{t}
|
||||
}(),
|
||||
options: []MigrateOption{WithDropIndex(true)},
|
||||
before: func(mock mysqlMock) {
|
||||
mock.start("5.7.23")
|
||||
mock.tableExists("users", true)
|
||||
mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ?")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("text", "longtext", "YES", "NO", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1").
|
||||
AddRow("prefix_text", "text", "50", "0", "1"))
|
||||
mock.ExpectQuery(escape("SELECT `CONSTRAINT_NAME` FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` WHERE `TABLE_NAME` = ? AND `COLUMN_NAME` = ? AND `POSITION_IN_UNIQUE_CONSTRAINT` IS NOT NULL AND `TABLE_SCHEMA` = (SELECT DATABASE())")).
|
||||
WithArgs("users", "text").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"CONSTRAINT_NAME"}))
|
||||
// modify index by dropping and creating it.
|
||||
mock.ExpectExec(escape("DROP INDEX `prefix_text` ON `users`")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectExec(escape("CREATE INDEX `prefix_text` ON `users`(`text`(100))")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ignore foreign keys on index dropping",
|
||||
tables: []*Table{
|
||||
@@ -818,12 +862,12 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("parent_id", "bigint(20)", "YES", "NULL", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1").
|
||||
AddRow("old_index", "old", "0", "1").
|
||||
AddRow("parent_id", "parent_id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1").
|
||||
AddRow("old_index", "old", nil, "0", "1").
|
||||
AddRow("parent_id", "parent_id", nil, "0", "1"))
|
||||
// drop the unique index.
|
||||
mock.ExpectExec(escape("DROP INDEX `old_index` ON `users`")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
@@ -854,11 +898,11 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("parent_id", "bigint(20)", "YES", "NULL", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1").
|
||||
AddRow("parent_id", "parent_id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1").
|
||||
AddRow("parent_id", "parent_id", nil, "0", "1"))
|
||||
// check if a foreign-key needs to be dropped.
|
||||
mock.ExpectQuery(escape("SELECT `CONSTRAINT_NAME` FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` WHERE `TABLE_NAME` = ? AND `COLUMN_NAME` = ? AND `POSITION_IN_UNIQUE_CONSTRAINT` IS NOT NULL AND `TABLE_SCHEMA` = (SELECT DATABASE())")).
|
||||
WithArgs("users", "parent_id").
|
||||
@@ -897,11 +941,11 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("parent_id", "bigint(20)", "YES", "NULL", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1").
|
||||
AddRow("parent_id", "parent_id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1").
|
||||
AddRow("parent_id", "parent_id", nil, "0", "1"))
|
||||
// check if there's a foreign-key that is associated with this index.
|
||||
mock.ExpectQuery(escape("SELECT `CONSTRAINT_NAME` FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` WHERE `TABLE_NAME` = ? AND `COLUMN_NAME` = ? AND `POSITION_IN_UNIQUE_CONSTRAINT` IS NOT NULL AND `TABLE_SCHEMA` = (SELECT DATABASE())")).
|
||||
WithArgs("users", "parent_id").
|
||||
@@ -949,10 +993,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectExec(escape("ALTER TABLE `users` ADD COLUMN `spouse_id` bigint NULL")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.fkExists("user_spouse_____________________390ed76f91d3c57cd3516e7690f621dc", false)
|
||||
@@ -1016,10 +1060,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
// query groups table.
|
||||
mock.ExpectQuery(escape("SELECT COUNT(*) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ?")).
|
||||
WithArgs("groups").
|
||||
@@ -1086,10 +1130,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
// query the auto-increment value.
|
||||
mock.ExpectQuery(escape("SELECT `AUTO_INCREMENT` FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ?")).
|
||||
WithArgs("users").
|
||||
@@ -1194,10 +1238,10 @@ func TestMySQL_Create(t *testing.T) {
|
||||
AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "").
|
||||
AddRow("json", "longtext", "YES", "YES", "NULL", "", "utf8mb4", "utf8mb4_bin").
|
||||
AddRow("longtext", "longtext", "YES", "YES", "NULL", "", "utf8mb4", "utf8mb4_bin"))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `sub_part`, `non_unique`, `seq_in_index` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? ORDER BY `index_name`, `seq_in_index`")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", "0", "1"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "sub_part", "non_unique", "seq_in_index"}).
|
||||
AddRow("PRIMARY", "id", nil, "0", "1"))
|
||||
mock.ExpectQuery(escape("SELECT `CONSTRAINT_NAME` FROM `INFORMATION_SCHEMA`.`CHECK_CONSTRAINTS` WHERE `CONSTRAINT_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ? AND `CHECK_CLAUSE` LIKE ?")).
|
||||
WithArgs("users", "json_valid(%)").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"CONSTRAINT_NAME"}).
|
||||
|
||||
@@ -112,6 +112,15 @@ func (t *Table) column(name string) (*Column, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Index returns a table index by its exact name.
|
||||
func (t *Table) Index(name string) (*Index, bool) {
|
||||
idx, ok := t.index(name)
|
||||
if ok && idx.Name == name {
|
||||
return idx, ok
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// index returns a table index by its name.
|
||||
func (t *Table) index(name string) (*Index, bool) {
|
||||
for _, idx := range t.Indexes {
|
||||
@@ -407,12 +416,13 @@ func (r ReferenceOption) ConstName() string {
|
||||
|
||||
// Index definition for table index.
|
||||
type Index struct {
|
||||
Name string // index name.
|
||||
Unique bool // uniqueness.
|
||||
Columns []*Column // actual table columns.
|
||||
columns []string // columns loaded from query scan.
|
||||
primary bool // primary key index.
|
||||
realname string // real name in the database (Postgres only).
|
||||
Name string // index name.
|
||||
Unique bool // uniqueness.
|
||||
Columns []*Column // actual table columns.
|
||||
Annotation *entsql.IndexAnnotation // index annotation.
|
||||
columns []string // columns loaded from query scan.
|
||||
primary bool // primary key index.
|
||||
realname string // real name in the database (Postgres only).
|
||||
}
|
||||
|
||||
// Builder returns the query builder for index creation. The DSL is identical in all dialects.
|
||||
|
||||
Reference in New Issue
Block a user