diff --git a/README.md b/README.md index 68a232e7..faafe812 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ For example for PostgreSQL you could pass `jsonb`and it will be supported, howev * `default_raw` - The default value defined as a database function. * `after` - (MySQL Only) Add a column after another column in the table. `example: {"after":"created_at"}` * `first` - (MySQL Only) Add a column to the first position in the table. `example: {"first": true}` +* `comment` - (MySQL Only) The comment of the column. `example: {"comment": "A comment"}` #### Composite primary key diff --git a/testdata/migrations/20160808213308_setup_tests.down.fizz b/testdata/migrations/20160808213308_setup_tests.down.fizz index 32186cc1..ad0507ae 100644 --- a/testdata/migrations/20160808213308_setup_tests.down.fizz +++ b/testdata/migrations/20160808213308_setup_tests.down.fizz @@ -4,4 +4,5 @@ drop_table("validatable_cars") drop_table("not_validatable_cars") drop_table("callbacks_users") drop_table("books") -drop_table("cars") \ No newline at end of file +drop_table("cars") +drop_table("user_with_comments") \ No newline at end of file diff --git a/testdata/migrations/20160808213308_setup_tests.up.fizz b/testdata/migrations/20160808213308_setup_tests.up.fizz index aff9db9f..a9afbbbd 100644 --- a/testdata/migrations/20160808213308_setup_tests.up.fizz +++ b/testdata/migrations/20160808213308_setup_tests.up.fizz @@ -43,3 +43,8 @@ create_table("taxis") { t.Column("model", "string") t.Column("user_id", "int", {null: true}) } + +create_table("user_with_comments", {"comment": "Table's comment"}) { + t.Column("id", "int", {"primary": true, "comment": "Identifier"}) + t.Column("email", "string", {"size": 20, "comment": "Private email"}) +} diff --git a/translators/mysql.go b/translators/mysql.go index 15631c3f..cabe35af 100644 --- a/translators/mysql.go +++ b/translators/mysql.go @@ -53,6 +53,9 @@ func (p *MySQL) CreateTable(t fizz.Table) (string, error) { } s := fmt.Sprintf("CREATE TABLE %s (\n%s\n) ENGINE=InnoDB;", p.escapeIdentifier(t.Name), strings.Join(cols, ",\n")) + if t.Options["comment"] != nil { + s = fmt.Sprintf("%s COMMENT='%v';", s[:len(s)-1], strings.ReplaceAll(fmt.Sprintf("%v", t.Options["comment"]), "'", "\\'")) + } sql = append(sql, s) for _, i := range t.Indexes { @@ -228,6 +231,9 @@ func (p *MySQL) buildColumn(c fizz.Column) string { if c.Primary && (c.ColType == "integer" || strings.HasSuffix(strings.ToLower(c.ColType), "int")) { s = fmt.Sprintf("%s AUTO_INCREMENT", s) } + if c.Options["comment"] != nil { + s = fmt.Sprintf("%s COMMENT '%v'", s, strings.ReplaceAll(fmt.Sprintf("%v", c.Options["comment"]), "'", "\\'")) + } return s } diff --git a/translators/mysql_meta.go b/translators/mysql_meta.go index 47fdb557..ad86489e 100644 --- a/translators/mysql_meta.go +++ b/translators/mysql_meta.go @@ -17,6 +17,7 @@ type mysqlTableInfo struct { Null string `db:"Null"` Key string `db:"Key"` Default interface{} `db:"Default"` + Comment string `db:"Comment"` Extra string `db:"Extra"` } @@ -34,6 +35,9 @@ func (ti mysqlTableInfo) ToColumn() fizz.Column { d := fmt.Sprintf("%s", ti.Default) c.Options["default"] = d } + if len(ti.Comment) > 0 { + c.Options["comment"] = ti.Comment + } return c } @@ -98,7 +102,7 @@ func (p *mysqlSchema) Build() error { } func (p *mysqlSchema) buildTableData(table *fizz.Table, db *sql.DB) error { - prag := fmt.Sprintf("SELECT COLUMN_NAME AS `Field`, COLUMN_TYPE AS `Type`, IS_NULLABLE AS `Null`, COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS `Extra` FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s';", table.Name) + prag := fmt.Sprintf("SELECT COLUMN_NAME AS `Field`, COLUMN_TYPE AS `Type`, IS_NULLABLE AS `Null`, COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, COLUMN_COMMENT AS `Comment`, EXTRA AS `Extra` FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s';", p.Name, table.Name) res, err := db.Query(prag) if err != nil { @@ -108,7 +112,7 @@ func (p *mysqlSchema) buildTableData(table *fizz.Table, db *sql.DB) error { for res.Next() { ti := mysqlTableInfo{} - err = res.Scan(&ti.Field, &ti.Type, &ti.Null, &ti.Key, &ti.Default, &ti.Extra) + err = res.Scan(&ti.Field, &ti.Type, &ti.Null, &ti.Key, &ti.Default, &ti.Comment, &ti.Extra) if err != nil { return err } diff --git a/translators/mysql_test.go b/translators/mysql_test.go index 5ad74830..a77f5162 100644 --- a/translators/mysql_test.go +++ b/translators/mysql_test.go @@ -199,6 +199,26 @@ PRIMARY KEY(` + "`user_id`" + `, ` + "`profile_id`" + `) r.Equal(ddl, res) } +func (p *MySQLSuite) Test_MySQL_CreateTables_WithComments() { + r := p.Require() + ddl := `CREATE TABLE ` + "`user_with_comments`" + ` ( +` + "`id`" + ` INTEGER NOT NULL AUTO_INCREMENT COMMENT 'Identifier', +PRIMARY KEY(` + "`id`" + `), +` + "`email`" + ` VARCHAR (20) NOT NULL COMMENT 'Private email', +` + "`created_at`" + ` DATETIME NOT NULL, +` + "`updated_at`" + ` DATETIME NOT NULL +) ENGINE=InnoDB COMMENT='Table\'s comment';` + + res, err := fizz.AString(` + create_table("user_with_comments", {"comment": "Table's comment"}) { + t.Column("id", "INT", {"primary": true, "comment": "Identifier"}) + t.Column("email", "string", {"size":20, "comment": "Private email"}) + } + `, myt) + r.NoError(err) + r.Equal(ddl, res) +} + func (p *MySQLSuite) Test_MySQL_DropTable() { r := p.Require() @@ -266,6 +286,16 @@ func (p *MySQLSuite) Test_MySQL_AddColumnFirst() { r.Equal(ddl, res) } +func (p *MySQLSuite) Test_MySQL_AddColumnWithComment() { + r := p.Require() + ddl := `ALTER TABLE ` + "`user_with_comments`" + ` ADD COLUMN ` + "`name`" + ` VARCHAR (50) NOT NULL COMMENT 'Username';` + + res, err := fizz.AString(`add_column("user_with_comments", "name", "string", {"size": 50, "comment": "Username"})`, myt) + r.NoError(err) + + r.Equal(ddl, res) +} + func (p *MySQLSuite) Test_MySQL_DropColumn() { r := p.Require() ddl := `ALTER TABLE ` + "`users`" + ` DROP COLUMN ` + "`mycolumn`" + `;`