mirror of
https://github.com/beego/bee.git
synced 2024-11-25 09:50:55 +00:00
support migrate generate sql
This commit is contained in:
parent
70886d4cfd
commit
67c1c05a45
22
g.go
22
g.go
@ -22,13 +22,14 @@ var cmdGenerate = &Command{
|
||||
Long: `
|
||||
bee generate scaffold [scaffoldname] [-fields=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
|
||||
The generate scaffold command will do a number of things for you.
|
||||
-fields: a list of database fields.
|
||||
-fields: a list of table fields.
|
||||
-driver: [mysql | postgresql | sqlite], the default is mysql
|
||||
-conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test
|
||||
example: bee generate scaffold post -fields="title:string,body:text"
|
||||
|
||||
bee generate model [modelname] [-fields=""]
|
||||
generate RESTFul model based on fields
|
||||
-fields: a list of table fields.
|
||||
|
||||
bee generate controller [controllerfile]
|
||||
generate RESTFul controllers
|
||||
@ -36,8 +37,9 @@ bee generate controller [controllerfile]
|
||||
bee generate view [viewpath]
|
||||
generate CRUD view in viewpath
|
||||
|
||||
bee generate migration [migrationfile]
|
||||
bee generate migration [migrationfile] [-fields=""]
|
||||
generate migration file for making database schema update
|
||||
-fields: a list of table fields.
|
||||
|
||||
bee generate docs
|
||||
generate swagger doc file
|
||||
@ -147,15 +149,19 @@ func generateCode(cmd *Command, args []string) {
|
||||
ColorLog("[INFO] Using '%s' as 'level'\n", level)
|
||||
generateAppcode(driver.String(), conn.String(), level.String(), tables.String(), curpath)
|
||||
case "migration":
|
||||
if len(args) == 2 {
|
||||
mname := args[1]
|
||||
ColorLog("[INFO] Using '%s' as migration name\n", mname)
|
||||
generateMigration(mname, curpath)
|
||||
} else {
|
||||
if len(args) < 2 {
|
||||
ColorLog("[ERRO] Wrong number of arguments\n")
|
||||
ColorLog("[HINT] Usage: bee generate migration [migrationname]\n")
|
||||
ColorLog("[HINT] Usage: bee generate migration [migrationname] [-fields=\"\"]\n")
|
||||
os.Exit(2)
|
||||
}
|
||||
cmd.Flag.Parse(args[2:])
|
||||
mname := args[1]
|
||||
ColorLog("[INFO] Using '%s' as migration name\n", mname)
|
||||
upsql := ""
|
||||
if fields != "" {
|
||||
upsql = `m.Sql("CREATE TABLE ` + mname + "(" + generateSQLFromFields(fields.String()) + `)");`
|
||||
}
|
||||
generateMigration(mname, upsql, "", curpath)
|
||||
case "controller":
|
||||
if len(args) == 2 {
|
||||
cname := args[1]
|
||||
|
@ -31,7 +31,7 @@ const (
|
||||
// generateMigration generates migration file template for database schema update.
|
||||
// The generated file template consists of an up() method for updating schema and
|
||||
// a down() method for reverting the update.
|
||||
func generateMigration(mname string, curpath string) {
|
||||
func generateMigration(mname, upsql, downsql, curpath string) {
|
||||
migrationFilePath := path.Join(curpath, "database", M_PATH)
|
||||
if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) {
|
||||
// create migrations directory
|
||||
@ -47,6 +47,8 @@ func generateMigration(mname string, curpath string) {
|
||||
defer f.Close()
|
||||
content := strings.Replace(MIGRATION_TPL, "{{StructName}}", camelCase(mname)+"_"+today, -1)
|
||||
content = strings.Replace(content, "{{CurrTime}}", today, -1)
|
||||
content = strings.Replace(content, "{{UpSQL}}", upsql, -1)
|
||||
content = strings.Replace(content, "{{DownSQL}}", downsql, -1)
|
||||
f.WriteString(content)
|
||||
// gofmt generated source code
|
||||
formatSourceCode(fpath)
|
||||
@ -85,10 +87,12 @@ func init() {
|
||||
// Run the migrations
|
||||
func (m *{{StructName}}) Up() {
|
||||
// use m.Sql("CREATE TABLE ...") to make schema update
|
||||
{{UpSQL}}
|
||||
}
|
||||
|
||||
// Reverse the migrations
|
||||
func (m *{{StructName}}) Down() {
|
||||
// use m.Sql("DROP TABLE ...") to reverse schema update
|
||||
{{DownSQL}}
|
||||
}
|
||||
`
|
||||
|
24
g_model.go
24
g_model.go
@ -71,30 +71,6 @@ func getStruct(structname, fields string) (string, error) {
|
||||
return structStr, nil
|
||||
}
|
||||
|
||||
func camelString(s string) string {
|
||||
data := make([]byte, 0, len(s))
|
||||
j := false
|
||||
k := false
|
||||
num := len(s) - 1
|
||||
for i := 0; i <= num; i++ {
|
||||
d := s[i]
|
||||
if k == false && d >= 'A' && d <= 'Z' {
|
||||
k = true
|
||||
}
|
||||
if d >= 'a' && d <= 'z' && (j || k == false) {
|
||||
d = d - 32
|
||||
j = false
|
||||
k = true
|
||||
}
|
||||
if k && d == '_' && num > i && s[i+1] >= 'a' && s[i+1] <= 'z' {
|
||||
j = true
|
||||
continue
|
||||
}
|
||||
data = append(data, d)
|
||||
}
|
||||
return string(data[:len(data)])
|
||||
}
|
||||
|
||||
// fields support type
|
||||
// http://beego.me/docs/mvc/model/models.md#mysql
|
||||
func getType(ktype string) (kt, tag string) {
|
||||
|
@ -1,6 +1,9 @@
|
||||
package main
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func generateScaffold(sname, fields, crupath, driver, conn string) {
|
||||
// generate model
|
||||
@ -22,7 +25,11 @@ func generateScaffold(sname, fields, crupath, driver, conn string) {
|
||||
// generate migration
|
||||
ColorLog("[INFO] Do you want me to create a %v migration and schema for this resource? [yes|no]] ", sname)
|
||||
if askForConfirmation() {
|
||||
generateMigration(sname, crupath)
|
||||
upsql := ""
|
||||
if fields != "" {
|
||||
upsql = `m.Sql("CREATE TABLE ` + sname + "(" + generateSQLFromFields(fields) + `)");`
|
||||
}
|
||||
generateMigration(sname, upsql, "", crupath)
|
||||
}
|
||||
// run migration
|
||||
ColorLog("[INFO] Do you want to go ahead and migrate the database? [yes|no]] ")
|
||||
@ -31,3 +38,62 @@ func generateScaffold(sname, fields, crupath, driver, conn string) {
|
||||
}
|
||||
ColorLog("[INFO] All done! Don't forget to add beego.Router(\"/%v\" ,&controllers.%vController{}) to routers/route.go\n", sname, strings.Title(sname))
|
||||
}
|
||||
|
||||
func generateSQLFromFields(fields string) string {
|
||||
sql := ""
|
||||
tags := ""
|
||||
fds := strings.Split(fields, ",")
|
||||
for i, v := range fds {
|
||||
kv := strings.SplitN(v, ":", 2)
|
||||
if len(kv) != 2 {
|
||||
ColorLog("[ERRO] the filds format is wrong. should key:type,key:type " + v)
|
||||
return ""
|
||||
}
|
||||
typ, tag := getSqlType(kv[1])
|
||||
if typ == "" {
|
||||
ColorLog("[ERRO] the filds format is wrong. should key:type,key:type " + v)
|
||||
return ""
|
||||
}
|
||||
if i == 0 && strings.ToLower(kv[0]) != "id" {
|
||||
sql = sql + "`id` int(11) NOT NULL AUTO_INCREMENT,"
|
||||
tags = tags + "PRIMARY KEY (`id`),"
|
||||
}
|
||||
sql = sql + "`" + snakeString(kv[0]) + "` " + typ + ","
|
||||
if tag != "" {
|
||||
tags = tags + fmt.Sprintf(tag, "`"+snakeString(kv[0])+"`") + ","
|
||||
}
|
||||
}
|
||||
sql = strings.TrimRight(sql+tags, ",")
|
||||
return sql
|
||||
}
|
||||
|
||||
func getSqlType(ktype string) (tp, tag string) {
|
||||
kv := strings.SplitN(ktype, ":", 2)
|
||||
switch kv[0] {
|
||||
case "string":
|
||||
if len(kv) == 2 {
|
||||
return "varchar(" + kv[1] + ") NOT NULL", ""
|
||||
} else {
|
||||
return "varchar(128) NOT NULL", ""
|
||||
}
|
||||
case "text":
|
||||
return "longtext NOT NULL", ""
|
||||
case "auto":
|
||||
return "int(11) NOT NULL AUTO_INCREMENT", ""
|
||||
case "pk":
|
||||
return "int(11) NOT NULL", "PRIMARY KEY (%s)"
|
||||
case "datetime":
|
||||
return "datetime NOT NULL", ""
|
||||
case "int", "int8", "int16", "int32", "int64":
|
||||
fallthrough
|
||||
case "uint", "uint8", "uint16", "uint32", "uint64":
|
||||
return "int(11) DEFAULT NULL", ""
|
||||
case "bool":
|
||||
return "tinyint(1) NOT NULL", ""
|
||||
case "float32", "float64":
|
||||
return "float NOT NULL", ""
|
||||
case "float":
|
||||
return "float NOT NULL", ""
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
|
42
util.go
42
util.go
@ -206,3 +206,45 @@ func containsString(slice []string, element string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// snake string, XxYy to xx_yy
|
||||
func snakeString(s string) string {
|
||||
data := make([]byte, 0, len(s)*2)
|
||||
j := false
|
||||
num := len(s)
|
||||
for i := 0; i < num; i++ {
|
||||
d := s[i]
|
||||
if i > 0 && d >= 'A' && d <= 'Z' && j {
|
||||
data = append(data, '_')
|
||||
}
|
||||
if d != '_' {
|
||||
j = true
|
||||
}
|
||||
data = append(data, d)
|
||||
}
|
||||
return strings.ToLower(string(data[:len(data)]))
|
||||
}
|
||||
|
||||
func camelString(s string) string {
|
||||
data := make([]byte, 0, len(s))
|
||||
j := false
|
||||
k := false
|
||||
num := len(s) - 1
|
||||
for i := 0; i <= num; i++ {
|
||||
d := s[i]
|
||||
if k == false && d >= 'A' && d <= 'Z' {
|
||||
k = true
|
||||
}
|
||||
if d >= 'a' && d <= 'z' && (j || k == false) {
|
||||
d = d - 32
|
||||
j = false
|
||||
k = true
|
||||
}
|
||||
if k && d == '_' && num > i && s[i+1] >= 'a' && s[i+1] <= 'z' {
|
||||
j = true
|
||||
continue
|
||||
}
|
||||
data = append(data, d)
|
||||
}
|
||||
return string(data[:len(data)])
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user