Migu is an idempotent database schema migration tool for Go.
Migu is inspired by Ridgepole.
go get -u github.com/naoina/migu/cmd/miguFirst, you write Go code to schema.go like below.
package yourownpackagename
//+migu
type User struct {
Name string
Age int
}Migu uses Go structs for migration that has annotation tag of +migu in struct comments.
Second, you enter the following commands to execute the first migration.
% mysqladmin -u root create migu_test
% migu sync -u root migu_test schema.go
% mysql -u root migu_test -e 'desc user'
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| name | varchar(255) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
+-------+--------------+------+-----+---------+-------+
If user table does not exist on the database, migu sync command will create user table into the database.
Finally, You modify schema.go as follows.
package yourownpackagename
//+migu
type User struct {
Name string
Age uint
}Then, run migu sync command again.
% migu sync -u root migu_test schema.go
% mysql -u root migu_test -e 'desc user'
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| name | varchar(255) | NO | | NULL | |
| age | int(10) unsigned | NO | | NULL | |
+-------+------------------+------+-----+---------+-------+
If a type of field of User struct is changed, migu sync command will change a type of age field on the database.
In above case, a type of Age field of User struct was changed from int to uint, so a type of age field of user table on the database has been changed from int to int unsigned by migu sync command.
See migu --help for more options.
You can specify the detailed definition of the column by some struct field tags.
ID int64 `migu:"pk"`You can specify pk struct field tag to multiple field to define the multiple-column primary key.
UserID int64 `migu:"pk"`
ProfileID int64 `migu:"pk"`ID int64 `migu:"autoincrement"`Email string `migu:"index"`If you want to give another index name, specify the index name as follows.
Email string `migu:"index:email_index"`You can also define multiple-column indexes by specifying the same index name to multiple fields.
Name string `migu:"index:name_email_index"`
Email string `migu:"index:name_email_index"`Email string `migu:"unique"`If you want to give another unique index name, specify the unique index name as follows.
Email string `migu:"unique:email_unique_index"`You can also define multiple-column unique indexes by specifying the same unique index name to multiple fields.
Name string `migu:"unique:name_email_unique_index"`
Email string `migu:"unique:name_email_unique_index"`Active bool `migu:"default:true"`If a field type is string, Migu surrounds a string value by dialect-specific quotes.
Active string `migu:"default:yes"`You can specify the column name on the database.
Body string `migu:"column:content"`To specify the type of column, please use type struct tag.
Balance float64 `migu:"type:decimal"`You can also use type struct tag to specify the different size of VARCHAR, VARBINARY, DECIMAL and so on.
Balance float64 `migu:"type:decimal(20,2)"`
UUID string `migu:"type:varchar(36)"`By default, A user-defined type will be NOT NULL. If you don't want to specify NOT NULL, you can use null struct tag like below.
Amount CustomType `migu:"type:int,null"`If you want to add an extra clause to column definition such as ON UPDATE CURRENT_TIMESTAMP, you can use extra field tag.
UpdatedAt time.Time `migu:"extra:ON UPDATE CURRENT_TIMESTAMP"`The clause specified by extra field tag will be added to trailing the column definition like below.
CREATE TABLE `user` (
`updated_at` DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP
)For Cloud Spanner,
ID int64 `migu:"pk"` // Every table of Cloud Spanner must have a primary key.
UpdatedAt time.Time `migu:"extra:allow_commit_timestamp = true"`CREATE TABLE `user` (
`id` INT64 NOT NULL,
`updated_at` TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp = true)
) PRIMARY KEY (`id`)Body string `migu:"-"` // This field does not affect the migration.To specify multiple struct field tags to a single column, join tags with commas.
Email string `migu:"unique,size:512"`If you want to define extra columns for the database table that is not related to struct fields, you can use _ field and column struct tag.
package model
import "time"
//+migu
type User struct {
Name string
_ time.Time `migu:"column:created_at"`
_ time.Time `migu:"column:updated_at"`
}This feature can be used for workaround that Migu cannot collect the columns information from fields of embedded fields.
For example, Timestamp struct is embedded to User struct.
package model
import "time"
type Timestamp struct {
CreatedAt time.Time
UpdatedAt time.Time
}
//+migu
type User struct {
Name string
Timestamp
}migu sync -u root --dry-run migu_test--------dry-run applying--------
CREATE TABLE `user` (
`name` VARCHAR(255) NOT NULL
)
--------dry-run done 0.000s--------
Timestamp embedded field does not appear in DDL. The reason for this restriction is that Migu uses Go AST to collect the struct information.
A way to avoid this restriction, you can add definition of some columns of Timestamp to _ fields in User struct.
package model
import "time"
type Timestamp struct {
CreatedAt time.Time
UpdatedAt time.Time
}
//+migu
type User struct {
Name string
Timestamp
_ time.Time `migu:"column:created_at"`
_ time.Time `migu:"column:updated_at"`
}--------dry-run applying--------
CREATE TABLE `user` (
`name` VARCHAR(255) NOT NULL,
`created_at` DATETIME NOT NULL,
`updated_at` DATETIME NOT NULL
)
--------dry-run done 0.000s--------
You can specify the some options to the table of database by annotation tags.
By default, Migu will decide the table name of the database from the name of Go struct. If you want to specify the different table name, use table annotation tag.
package model
//+migu table:"guest"
type User struct {
Name string
}--------dry-run applying--------
CREATE TABLE `guest` (
`name` VARCHAR(255) NOT NULL
)
--------dry-run done 0.000s--------
If you want to specify a table option such as ENGINE, DEFAULT CHARSET, ROW_FORMAT, and so on, use option annotation tag.
package model
//+migu option:"ENGINE=InnoDB ROW_FORMAT=DYNAMIC"
type User struct {
Name string
}--------dry-run applying--------
CREATE TABLE `user` (
`name` VARCHAR(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC
--------dry-run done 0.000s--------
- MariaDB/MySQL
- Cloud Spanner
It is when a Pull Request comes from you!
MIT