diff --git a/.golangci.yml b/.golangci.yml index 1abb6aaf4..2d7956e43 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -7,8 +7,8 @@ linters-settings: dupl: threshold: 100 funlen: - lines: 100 - statements: 80 + lines: 110 + statements: 100 goheader: template: |- Copyright 2019-present Facebook Inc. All rights reserved. diff --git a/dialect/sql/schema/inspect_test.go b/dialect/sql/schema/inspect_test.go index 7be64dc5b..cfc3fad01 100644 --- a/dialect/sql/schema/inspect_test.go +++ b/dialect/sql/schema/inspect_test.go @@ -60,41 +60,42 @@ func TestInspector_Tables(t *testing.T) { AddRow("pets"). AddRow("groups"). AddRow("user_groups")) - 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?")). WithArgs("public", "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("name", "varchar(255)", "YES", "YES", "NULL", "", "", ""). - AddRow("text", "longtext", "YES", "YES", "NULL", "", "", ""). - AddRow("uuid", "char(36)", "YES", "YES", "NULL", "", "", "utf8mb4_bin")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "", nil, nil). + AddRow("text", "longtext", "YES", "YES", "NULL", "", "", "", nil, nil). + AddRow("uuid", "char(36)", "YES", "YES", "NULL", "", "", "utf8mb4_bin", nil, nil). + AddRow("price", "decimal(6, 4)", "NO", "YES", "NULL", "", "", "", "6", "4")) 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", "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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "", nil, nil). + AddRow("user_pets", "bigint(20)", "YES", "YES", "NULL", "", "", "", nil, nil)) 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", "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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", "", nil, nil)) 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", "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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("user_id", "bigint(20)", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("group_id", "bigint(20)", "NO", "YES", "NULL", "", "", "", nil, nil)) 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", "sub_part", "non_unique", "seq_in_index"})) @@ -113,7 +114,8 @@ func TestInspector_Tables(t *testing.T) { AddRow("id", "integer", 1, "NULL", 1). AddRow("name", "varchar(255)", 0, "NULL", 0). AddRow("text", "text", 0, "NULL", 0). - AddRow("uuid", "uuid", 0, "NULL", 0)) + AddRow("uuid", "uuid", 0, "NULL", 0). + AddRow("price", "real", 1, "NULL", 0)) mock.ExpectQuery(escape("SELECT `name`, `unique`, `origin` FROM pragma_index_list('users')")). WillReturnRows(sqlmock.NewRows([]string{"name", "unique", "unique"})) mock.ExpectQuery(escape("SELECT `name`, `type`, `notnull`, `dflt_value`, `pk` FROM pragma_table_info('pets') ORDER BY `pk`")). @@ -147,41 +149,42 @@ func TestInspector_Tables(t *testing.T) { AddRow("pets"). AddRow("groups"). AddRow("user_groups")) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = $1 AND "table_name" = $2`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = $1 AND "table_name" = $2`)). WithArgs("public", "users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character", "YES", "NULL", "bpchar"). - AddRow("text", "text", "YES", "NULL", "text"). - AddRow("uuid", "uuid", "YES", "NULL", "uuid")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character", "YES", "NULL", "bpchar", nil, nil). + AddRow("text", "text", "YES", "NULL", "text", nil, nil). + AddRow("uuid", "uuid", "YES", "NULL", "uuid", nil, nil). + AddRow("price", "numeric", "NO", "NULL", "numeric", "6", "4")) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "$1", "users"))). WithArgs("public"). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = $1 AND "table_name" = $2`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = $1 AND "table_name" = $2`)). WithArgs("public", "pets"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character", "YES", "NULL", "bpchar"). - AddRow("user_pets", "bigint", "YES", "NULL", "int8")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character", "YES", "NULL", "bpchar", nil, nil). + AddRow("user_pets", "bigint", "YES", "NULL", "int8", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "$1", "pets"))). WithArgs("public"). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("pets_pkey", "id", "t", "t", 0)) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = $1 AND "table_name" = $2`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = $1 AND "table_name" = $2`)). WithArgs("public", "groups"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character", "NO", "NULL", "bpchar")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character", "NO", "NULL", "bpchar", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "$1", "groups"))). WithArgs("public"). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("groups_pkey", "id", "t", "t", 0)) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = $1 AND "table_name" = $2`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = $1 AND "table_name" = $2`)). WithArgs("public", "user_groups"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("user_id", "bigint", "NO", "NULL", "int8"). - AddRow("group_id", "bigint", "NO", "NULL", "int8")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("user_id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("group_id", "bigint", "NO", "NULL", "int8", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "$1", "user_groups"))). WithArgs("public"). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"})) @@ -205,6 +208,10 @@ func TestInspector_Tables(t *testing.T) { {Name: "name", Type: field.TypeString, Size: 255, Nullable: true}, {Name: "text", Type: field.TypeString, Size: math.MaxInt32, Nullable: true}, {Name: "uuid", Type: field.TypeUUID, Nullable: true}, + {Name: "price", Type: field.TypeFloat64, SchemaType: map[string]string{ + dialect.MySQL: "decimal(6,4)", + dialect.Postgres: "numeric(6,4)", + }}, } t1 = &Table{ Name: "users", @@ -280,38 +287,41 @@ func TestInspector_Tables(t *testing.T) { require.NoError(t, err) tables, err := inspect.Tables(context.Background()) require.Equal(t, tt.wantErr, err != nil, err) - tablesMatch(t, tables, tt.tables(drv)) + tablesMatch(t, drv, tables, tt.tables(drv)) }) } } } -func tablesMatch(t *testing.T, got, expected []*Table) { +func tablesMatch(t *testing.T, drv string, got, expected []*Table) { require.Equal(t, len(expected), len(got)) for i := range got { - columnsMatch(t, got[i].Columns, expected[i].Columns) - columnsMatch(t, got[i].PrimaryKey, expected[i].PrimaryKey) - foreignKeysMatch(t, got[i].ForeignKeys, expected[i].ForeignKeys) + columnsMatch(t, drv, got[i].Columns, expected[i].Columns) + columnsMatch(t, drv, got[i].PrimaryKey, expected[i].PrimaryKey) + foreignKeysMatch(t, drv, got[i].ForeignKeys, expected[i].ForeignKeys) } } -func columnsMatch(t *testing.T, got, expected []*Column) { +func columnsMatch(t *testing.T, drv string, got, expected []*Column) { require.Equal(t, len(expected), len(got)) for i := range got { c1, c2 := got[i], expected[i] - require.Equal(t, c1.Name, c2.Name) - require.Equal(t, c1.Nullable, c2.Nullable) + require.Equal(t, c2.Name, c1.Name) + require.Equal(t, c2.Nullable, c1.Nullable) require.True(t, c1.Type == c2.Type || c1.ConvertibleTo(c2), "mismatched types: %s - %s", c1.Type, c2.Type) + if c2.SchemaType[drv] != "" { + require.Equal(t, c2.SchemaType[drv], c1.SchemaType[drv]) + } } } -func foreignKeysMatch(t *testing.T, expected []*ForeignKey, got []*ForeignKey) { +func foreignKeysMatch(t *testing.T, drv string, expected []*ForeignKey, got []*ForeignKey) { require.Equal(t, len(expected), len(got)) for i := range got { fk1, fk2 := got[i], expected[i] - require.Equal(t, fk1.Symbol, fk2.Symbol) - require.Equal(t, fk1.RefTable.Name, fk2.RefTable.Name) - columnsMatch(t, fk1.Columns, fk2.Columns) - columnsMatch(t, fk1.RefColumns, fk2.RefColumns) + require.Equal(t, fk2.Symbol, fk1.Symbol) + require.Equal(t, fk2.RefTable.Name, fk1.RefTable.Name) + columnsMatch(t, drv, fk1.Columns, fk2.Columns) + columnsMatch(t, drv, fk1.RefColumns, fk2.RefColumns) } } diff --git a/dialect/sql/schema/migrate.go b/dialect/sql/schema/migrate.go index bea5ce632..26d72ccc7 100644 --- a/dialect/sql/schema/migrate.go +++ b/dialect/sql/schema/migrate.go @@ -189,7 +189,7 @@ func (m *Migrate) txCreate(ctx context.Context, tx dialect.Tx, tables ...*Table) } change, err := m.changeSet(curr, t) if err != nil { - return err + return fmt.Errorf("creating changeset for %q: %w", t.Name, err) } if err := m.apply(ctx, tx, t.Name, change); err != nil { return err diff --git a/dialect/sql/schema/mysql.go b/dialect/sql/schema/mysql.go index ddd2564ac..00d21f075 100644 --- a/dialect/sql/schema/mysql.go +++ b/dialect/sql/schema/mysql.go @@ -67,7 +67,10 @@ func (d *MySQL) fkExist(ctx context.Context, tx dialect.Tx, name string) (bool, // table loads the current table description from the database. func (d *MySQL) table(ctx context.Context, tx dialect.Tx, name string) (*Table, error) { rows := &sql.Rows{} - query, args := sql.Select("column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"). + query, args := sql.Select( + "column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", + "numeric_precision", "numeric_scale", + ). From(sql.Table("COLUMNS").Schema("INFORMATION_SCHEMA")). Where(sql.And( d.matchSchema(), @@ -377,12 +380,15 @@ func (d *MySQL) prepare(ctx context.Context, tx dialect.Tx, change *changes, tab } // scanColumn scans the column information from MySQL column description. +// nolint:funlen func (d *MySQL) scanColumn(c *Column, rows *sql.Rows) error { var ( - nullable sql.NullString - defaults sql.NullString + nullable sql.NullString + defaults sql.NullString + numericPrecision sql.NullInt64 + numericScale sql.NullInt64 ) - if err := rows.Scan(&c.Name, &c.typ, &nullable, &c.Key, &defaults, &c.Attr, &sql.NullString{}, &sql.NullString{}); err != nil { + if err := rows.Scan(&c.Name, &c.typ, &nullable, &c.Key, &defaults, &c.Attr, &sql.NullString{}, &sql.NullString{}, &numericPrecision, &numericScale); err != nil { return fmt.Errorf("scanning column description: %w", err) } c.Unique = c.UniqueKey() @@ -421,8 +427,15 @@ func (d *MySQL) scanColumn(c *Column, rows *sql.Rows) error { default: c.Type = field.TypeInt8 } - case "numeric", "decimal", "double": + case "double": c.Type = field.TypeFloat64 + case "numeric", "decimal": + c.Type = field.TypeFloat64 + // If precision is specified then we should take that into account. + if numericPrecision.Valid { + schemaType := fmt.Sprintf("%s(%d,%d)", parts[0], numericPrecision.Int64, numericScale.Int64) + c.SchemaType = map[string]string{dialect.MySQL: schemaType} + } case "time", "timestamp", "date", "datetime": c.Type = field.TypeTime // The mapping from schema defaults to database diff --git a/dialect/sql/schema/mysql_test.go b/dialect/sql/schema/mysql_test.go index 8814e8a51..7a0650c82 100644 --- a/dialect/sql/schema/mysql_test.go +++ b/dialect/sql/schema/mysql_test.go @@ -272,24 +272,24 @@ func TestMySQL_Create(t *testing.T) { before: func(mock mysqlMock) { mock.start("8.0.19") 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "YES", "YES", "NULL", "", "", ""). - AddRow("text", "longtext", "YES", "YES", "NULL", "", "", ""). - AddRow("uuid", "char(36)", "YES", "YES", "NULL", "", "", "utf8mb4_bin"). - AddRow("date", "date", "YES", "YES", "NULL", "", "", ""). + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "", nil, nil). + AddRow("text", "longtext", "YES", "YES", "NULL", "", "", "", nil, nil). + AddRow("uuid", "char(36)", "YES", "YES", "NULL", "", "", "utf8mb4_bin", nil, nil). + AddRow("date", "date", "YES", "YES", "NULL", "", "", "", nil, nil). // 8.0.19: new int column type formats - AddRow("tiny", "tinyint", "NO", "YES", "NULL", "", "", ""). - AddRow("tiny_unsigned", "tinyint unsigned", "NO", "YES", "NULL", "", "", ""). - AddRow("small", "smallint", "NO", "YES", "NULL", "", "", ""). - AddRow("small_unsigned", "smallint unsigned", "NO", "YES", "NULL", "", "", ""). - AddRow("big", "bigint", "NO", "YES", "NULL", "", "", ""). - AddRow("big_unsigned", "bigint unsigned", "NO", "YES", "NULL", "", "", ""). - 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", "", "")) + AddRow("tiny", "tinyint", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("tiny_unsigned", "tinyint unsigned", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("small", "smallint", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("small_unsigned", "smallint unsigned", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("big", "bigint", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("big_unsigned", "bigint unsigned", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("decimal", "decimal(6,2)", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("unsigned_decimal", "decimal(6,2) unsigned", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("timestamp", "timestamp", "NO", "NO", "CURRENT_TIMESTAMP", "DEFAULT_GENERATED on update CURRENT_TIMESTAMP", "", "", nil, nil)) 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"}). @@ -318,13 +318,13 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "YES", "YES", "NULL", "", "", ""). - AddRow("enums1", "enum('a')", "YES", "NO", "NULL", "", "", ""). - AddRow("enums2", "enum('b', 'a')", "NO", "YES", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "", nil, nil). + AddRow("enums1", "enum('a')", "YES", "NO", "NULL", "", "", "", nil, nil). + AddRow("enums2", "enum('b', 'a')", "NO", "YES", "NULL", "", "", "", nil, nil)) 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"}). @@ -353,13 +353,13 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("created_at", "datetime", "NO", "YES", "NULL", "", "", ""). - AddRow("updated_at", "timestamp", "NO", "YES", "NULL", "", "", ""). - AddRow("deleted_at", "datetime", "NO", "YES", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("created_at", "datetime", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("updated_at", "timestamp", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("deleted_at", "datetime", "NO", "YES", "NULL", "", "", "", nil, nil)) 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"}). @@ -388,12 +388,12 @@ func TestMySQL_Create(t *testing.T) { before: func(mock mysqlMock) { mock.start("5.6.0") 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "YES", "YES", "NULL", "", "", ""). - AddRow("doc", "longblob", "YES", "YES", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "", nil, nil). + AddRow("doc", "longblob", "YES", "YES", "NULL", "", "", "", nil, nil)) 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"}). @@ -423,10 +423,10 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil)) 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"}). @@ -453,10 +453,10 @@ func TestMySQL_Create(t *testing.T) { before: func(mock mysqlMock) { mock.start("8.0.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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil)) 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"}). @@ -484,12 +484,12 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("tiny", "varbinary(255)", "NO", "YES", "NULL", "", "", ""). - AddRow("medium", "varbinary(255)", "NO", "YES", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("tiny", "varbinary(255)", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("medium", "varbinary(255)", "NO", "YES", "NULL", "", "", "", nil, nil)) 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"}). @@ -517,11 +517,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "NO", "YES", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", "", nil, nil)) 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"}). @@ -549,11 +549,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "NO", "YES", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", "", nil, nil)) 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"}). @@ -581,11 +581,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "YES", "YES", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "", nil, nil)) 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"}). @@ -613,11 +613,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "YES", "YES", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "", nil, nil)) 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"}). @@ -644,11 +644,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "NO", "YES", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", "", nil, nil)) 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"}). @@ -676,12 +676,12 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "NO", "YES", "NULL", "", "", ""). - AddRow("age", "bigint(20)", "NO", "NO", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", "", nil, nil). + AddRow("age", "bigint(20)", "NO", "NO", "NULL", "", "", "", nil, nil)) 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"}). @@ -708,11 +708,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("age", "bigint(20)", "NO", "", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("age", "bigint(20)", "NO", "", "NULL", "", "", "", nil, nil)) 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"}). @@ -740,11 +740,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("age", "bigint(20)", "NO", "UNI", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("age", "bigint(20)", "NO", "UNI", "NULL", "", "", "", nil, nil)) 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"}). @@ -771,11 +771,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("age", "bigint(20)", "NO", "UNI", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("age", "bigint(20)", "NO", "UNI", "NULL", "", "", "", nil, nil)) 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"}). @@ -814,11 +814,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("text", "longtext", "YES", "NO", "NULL", "", "", "", nil, nil)) 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"}). @@ -861,11 +861,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("parent_id", "bigint(20)", "YES", "NULL", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("parent_id", "bigint(20)", "YES", "NULL", "NULL", "", "", "", nil, nil)) 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"}). @@ -897,11 +897,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("parent_id", "bigint(20)", "YES", "NULL", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("parent_id", "bigint(20)", "YES", "NULL", "NULL", "", "", "", nil, nil)) 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"}). @@ -940,11 +940,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("parent_id", "bigint(20)", "YES", "NULL", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("parent_id", "bigint(20)", "YES", "NULL", "NULL", "", "", "", nil, nil)) 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"}). @@ -992,11 +992,11 @@ func TestMySQL_Create(t *testing.T) { 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "YES", "YES", "NULL", "", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "", nil, nil)) 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"}). @@ -1060,10 +1060,10 @@ func TestMySQL_Create(t *testing.T) { WillReturnRows(sqlmock.NewRows([]string{"type"}).AddRow("users")) mock.tableExists("users", true) // users table has no changes. - 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil)) 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"}). @@ -1130,10 +1130,10 @@ func TestMySQL_Create(t *testing.T) { AddRow("users")) mock.tableExists("users", true) // users table has no changes. - 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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", "", "")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil)) 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"}). @@ -1149,6 +1149,66 @@ func TestMySQL_Create(t *testing.T) { mock.ExpectCommit() }, }, + { + name: "no modify numeric column", + tables: []*Table{ + { + Name: "users", + Columns: []*Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "price", Type: field.TypeFloat64, SchemaType: map[string]string{dialect.MySQL: "decimal(6,4)"}}, + }, + PrimaryKey: []*Column{ + {Name: "id", Type: field.TypeInt, Increment: 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`, `numeric_precision`, `numeric_scale` 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", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("price", "decimal(6,4)", "NO", "YES", "NULL", "", "", "", "6", "4")) + 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")) + mock.ExpectCommit() + }, + }, + { + name: "modify numeric column", + tables: []*Table{ + { + Name: "users", + Columns: []*Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "price", Type: field.TypeFloat64, SchemaType: map[string]string{dialect.MySQL: "decimal(6,4)"}}, + }, + PrimaryKey: []*Column{ + {Name: "id", Type: field.TypeInt, Increment: 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`, `numeric_precision`, `numeric_scale` 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", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("price", "decimal(6,4)", "NO", "YES", "NULL", "", "", "", "5", "4")) + 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")) + mock.ExpectExec(escape("ALTER TABLE `users` MODIFY COLUMN `price` decimal(6,4) NOT NULL")). + WillReturnResult(sqlmock.NewResult(0, 1)) + mock.ExpectCommit() + }, + }, // MariaDB specific tests. { name: "mariadb/10.2.32/create table", @@ -1235,13 +1295,13 @@ func TestMySQL_Create(t *testing.T) { before: func(mock mysqlMock) { mock.start("10.5.8-MariaDB-1:10.5.8+maria~focal") 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` = ?")). + mock.ExpectQuery(escape("SELECT `column_name`, `column_type`, `is_nullable`, `column_key`, `column_default`, `extra`, `character_set_name`, `collation_name`, `numeric_precision`, `numeric_scale` 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("name", "varchar(255)", "YES", "YES", "NULL", "", "", ""). - AddRow("json", "longtext", "YES", "YES", "NULL", "", "utf8mb4", "utf8mb4_bin"). - AddRow("longtext", "longtext", "YES", "YES", "NULL", "", "utf8mb4", "utf8mb4_bin")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "", nil, nil). + AddRow("name", "varchar(255)", "YES", "YES", "NULL", "", "", "", nil, nil). + AddRow("json", "longtext", "YES", "YES", "NULL", "", "utf8mb4", "utf8mb4_bin", nil, nil). + AddRow("longtext", "longtext", "YES", "YES", "NULL", "", "utf8mb4", "utf8mb4_bin", nil, nil)) 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"}). diff --git a/dialect/sql/schema/postgres.go b/dialect/sql/schema/postgres.go index dfaae527b..d8d5da3d8 100644 --- a/dialect/sql/schema/postgres.go +++ b/dialect/sql/schema/postgres.go @@ -90,7 +90,10 @@ func (d *Postgres) setRange(ctx context.Context, tx dialect.Tx, t *Table, value func (d *Postgres) table(ctx context.Context, tx dialect.Tx, name string) (*Table, error) { rows := &sql.Rows{} query, args := sql.Dialect(dialect.Postgres). - Select("column_name", "data_type", "is_nullable", "column_default", "udt_name"). + Select( + "column_name", "data_type", "is_nullable", "column_default", "udt_name", + "numeric_precision", "numeric_scale", + ). From(sql.Table("columns").Schema("information_schema")). Where(sql.And( d.matchSchema(), @@ -226,11 +229,13 @@ const maxCharSize = 10 << 20 // scanColumn scans the information a column from column description. func (d *Postgres) scanColumn(c *Column, rows *sql.Rows) error { var ( - nullable sql.NullString - defaults sql.NullString - udt sql.NullString + nullable sql.NullString + defaults sql.NullString + udt sql.NullString + numericPrecision sql.NullInt64 + numericScale sql.NullInt64 ) - if err := rows.Scan(&c.Name, &c.typ, &nullable, &defaults, &udt); err != nil { + if err := rows.Scan(&c.Name, &c.typ, &nullable, &defaults, &udt, &numericPrecision, &numericScale); err != nil { return fmt.Errorf("scanning column description: %w", err) } if nullable.Valid { @@ -247,8 +252,15 @@ func (d *Postgres) scanColumn(c *Column, rows *sql.Rows) error { c.Type = field.TypeInt64 case "real": c.Type = field.TypeFloat32 - case "numeric", "decimal", "double precision": + case "double precision": c.Type = field.TypeFloat64 + case "numeric", "decimal": + c.Type = field.TypeFloat64 + // If precision is specified then we should take that into account. + if numericPrecision.Valid { + schemaType := fmt.Sprintf("%s(%d,%d)", c.typ, numericPrecision.Int64, numericScale.Int64) + c.SchemaType = map[string]string{dialect.Postgres: schemaType} + } case "text": c.Type = field.TypeString c.Size = maxCharSize + 1 diff --git a/dialect/sql/schema/postgres_test.go b/dialect/sql/schema/postgres_test.go index a0949cd68..f8c463982 100644 --- a/dialect/sql/schema/postgres_test.go +++ b/dialect/sql/schema/postgres_test.go @@ -199,10 +199,10 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "nextval('users_colname_seq'::regclass)", "int4")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "nextval('users_colname_seq'::regclass)", "int4", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -226,11 +226,11 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "nextval('users_colname_seq'::regclass)", "NULL"). - AddRow("custom", "USER-DEFINED", "NO", "NULL", "customtype")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "nextval('users_colname_seq'::regclass)", "NULL", nil, nil). + AddRow("custom", "USER-DEFINED", "NO", "NULL", "customtype", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -265,21 +265,21 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character varying", "YES", "NULL", "varchar"). - AddRow("uuid", "uuid", "YES", "NULL", "uuid"). - AddRow("created_at", "date", "NO", "CURRENT_DATE", "date"). - AddRow("updated_at", "timestamp", "YES", "NULL", "timestamptz"). - AddRow("deleted_at", "date", "YES", "NULL", "date"). - AddRow("text", "text", "YES", "NULL", "text"). - AddRow("cidr", "cidr", "NO", "NULL", "cidr"). - AddRow("inet", "inet", "YES", "NULL", "inet"). - AddRow("macaddr", "macaddr", "YES", "NULL", "macaddr"). - AddRow("macaddr8", "macaddr8", "YES", "NULL", "macaddr8"). - AddRow("strings", "ARRAY", "YES", "NULL", "_text")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character varying", "YES", "NULL", "varchar", nil, nil). + AddRow("uuid", "uuid", "YES", "NULL", "uuid", nil, nil). + AddRow("created_at", "date", "NO", "CURRENT_DATE", "date", nil, nil). + AddRow("updated_at", "timestamp", "YES", "NULL", "timestamptz", nil, nil). + AddRow("deleted_at", "date", "YES", "NULL", "date", nil, nil). + AddRow("text", "text", "YES", "NULL", "text", nil, nil). + AddRow("cidr", "cidr", "NO", "NULL", "cidr", nil, nil). + AddRow("inet", "inet", "YES", "NULL", "inet", nil, nil). + AddRow("macaddr", "macaddr", "YES", "NULL", "macaddr", nil, nil). + AddRow("macaddr8", "macaddr8", "YES", "NULL", "macaddr8", nil, nil). + AddRow("strings", "ARRAY", "YES", "NULL", "_text", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -307,12 +307,12 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character", "YES", "NULL", "bpchar"). - AddRow("doc", "jsonb", "YES", "NULL", "jsonb")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character", "YES", "NULL", "bpchar", nil, nil). + AddRow("doc", "jsonb", "YES", "NULL", "jsonb", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -341,12 +341,12 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character", "YES", "NULL", "bpchar"). - AddRow("doc", "jsonb", "YES", "NULL", "jsonb")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character", "YES", "NULL", "bpchar", nil, nil). + AddRow("doc", "jsonb", "YES", "NULL", "jsonb", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -373,11 +373,11 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character", "YES", "NULL", "bpchar")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character", "YES", "NULL", "bpchar", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -404,11 +404,11 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character", "YES", "NULL", "bpchar")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character", "YES", "NULL", "bpchar", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -435,11 +435,11 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character", "YES", "NULL", "bpchar")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character", "YES", "NULL", "bpchar", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -465,11 +465,11 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character", "YES", "NULL", "bpchar")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character", "YES", "NULL", "bpchar", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -495,11 +495,11 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("name", "character", "NO", "NULL", "bpchar")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("name", "character", "NO", "NULL", "bpchar", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -525,11 +525,11 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("age", "bigint", "NO", "NULL", "int8")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("age", "bigint", "NO", "NULL", "int8", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -555,11 +555,11 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("age", "bigint", "NO", "NULL", "int8")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("age", "bigint", "NO", "NULL", "int8", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0). @@ -585,11 +585,11 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("age", "bigint", "NO", "NULL", "int8")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("age", "bigint", "NO", "NULL", "int8", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0). @@ -639,12 +639,12 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("age", "bigint", "NO", "NULL", "int8"). - AddRow("score", "bigint", "NO", "NULL", "int8")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("age", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("score", "bigint", "NO", "NULL", "int8", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0). @@ -660,11 +660,11 @@ func TestPostgres_Create(t *testing.T) { mock.ExpectExec(escape(`CREATE UNIQUE INDEX IF NOT EXISTS "user_score" ON "users"("score")`)). WillReturnResult(sqlmock.NewResult(0, 1)) mock.tableExists("equipment", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("equipment"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "NO", "NULL", "int8"). - AddRow("score", "bigint", "NO", "NULL", "int8")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("score", "bigint", "NO", "NULL", "int8", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "equipment"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0). @@ -701,11 +701,11 @@ func TestPostgres_Create(t *testing.T) { before: func(mock pgMock) { mock.start("120000") mock.tableExists("users", true) - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "YES", "NULL", "int8"). - AddRow("name", "character", "YES", "NULL", "bpchar")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "YES", "NULL", "int8", nil, nil). + AddRow("name", "character", "YES", "NULL", "bpchar", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -767,10 +767,10 @@ func TestPostgres_Create(t *testing.T) { // query users table. mock.tableExists("users", true) // users table has no changes. - mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). WithArgs("users"). - WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name"}). - AddRow("id", "bigint", "YES", "NULL", "int8")) + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "YES", "NULL", "int8", nil, nil)) mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). AddRow("users_pkey", "id", "t", "t", 0)) @@ -820,6 +820,64 @@ func TestPostgres_Create(t *testing.T) { mock.ExpectCommit() }, }, + { + name: "no modify numeric column", + tables: []*Table{ + { + Name: "users", + Columns: []*Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "price", Type: field.TypeFloat64, SchemaType: map[string]string{dialect.Postgres: "numeric(6,4)"}}, + }, + PrimaryKey: []*Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + }, + }, + }, + before: func(mock pgMock) { + mock.start("120000") + mock.tableExists("users", true) + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + WithArgs("users"). + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("price", "numeric", "NO", "NULL", "numeric", "6", "4")) + mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). + WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). + AddRow("users_pkey", "id", "t", "t", 0)) + mock.ExpectCommit() + }, + }, + { + name: "modify numeric column", + tables: []*Table{ + { + Name: "users", + Columns: []*Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "price", Type: field.TypeFloat64, Nullable: false, SchemaType: map[string]string{dialect.Postgres: "numeric(6,4)"}}, + }, + PrimaryKey: []*Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + }, + }, + }, + before: func(mock pgMock) { + mock.start("120000") + mock.tableExists("users", true) + mock.ExpectQuery(escape(`SELECT "column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale" FROM "information_schema"."columns" WHERE "table_schema" = CURRENT_SCHEMA() AND "table_name" = $1`)). + WithArgs("users"). + WillReturnRows(sqlmock.NewRows([]string{"column_name", "data_type", "is_nullable", "column_default", "udt_name", "numeric_precision", "numeric_scale"}). + AddRow("id", "bigint", "NO", "NULL", "int8", nil, nil). + AddRow("price", "numeric", "NO", "NULL", "numeric", "5", "4")) + mock.ExpectQuery(escape(fmt.Sprintf(indexesQuery, "CURRENT_SCHEMA()", "users"))). + WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "primary", "unique", "seq_in_index"}). + AddRow("users_pkey", "id", "t", "t", 0)) + mock.ExpectExec(escape(`ALTER TABLE "users" ALTER COLUMN "price" TYPE numeric(6,4), ALTER COLUMN "price" SET NOT NULL`)). + WillReturnResult(sqlmock.NewResult(0, 1)) + mock.ExpectCommit() + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {