package main import ( "flag" "fmt" "io/ioutil" "os" "os/exec" "path/filepath" "regexp" "strings" "github.com/zeromicro/ddl-parser/parser" "golang.org/x/text/cases" "golang.org/x/text/language" ) var targerDir = "ddl" var genDir = "model/gmodel_gen" func toPascalCase(s string) string { words := strings.Split(s, "_") for i, word := range words { words[i] = cases.Title(language.English).String(strings.ToLower(word)) } return strings.Join(words, "") } const ( _ int = iota LongVarBinary LongVarChar GeometryCollection GeomCollection LineString MultiLineString MultiPoint MultiPolygon Point Polygon Json Geometry Enum Set Bit Time Timestamp DateTime Binary VarBinary Blob Year Decimal Dec Fixed Numeric Float Float4 Float8 Double Real TinyInt SmallInt MediumInt Int Integer BigInt MiddleInt Int1 Int2 Int3 Int4 Int8 Date TinyBlob MediumBlob LongBlob Bool Boolean Serial NVarChar NChar Char Character VarChar TinyText Text MediumText LongText ) var SQLTypeToGoTypeMap = map[int]string{ LongVarBinary: "[]byte", Binary: "[]byte", VarBinary: "[]byte", Blob: "[]byte", TinyBlob: "[]byte", MediumBlob: "[]byte", LongBlob: "[]byte", LongVarChar: "*string", NVarChar: "*string", NChar: "*string", Char: "*string", Character: "*string", VarChar: "*string", TinyText: "*string", Text: "*string", MediumText: "*string", LongText: "*string", Time: "*time.Time", Timestamp: "*time.Time", DateTime: "*time.Time", Date: "*time.Time", Year: "*int64", TinyInt: "*int64", SmallInt: "*int64", MediumInt: "*int64", Int: "*int64", Integer: "*int64", BigInt: "*int64", MiddleInt: "*int64", Int1: "*int64", Int2: "*int64", Int3: "*int64", Int4: "*int64", Int8: "*int64", Serial: "*int64", Decimal: "*float64", Dec: "*float64", Fixed: "*float64", Numeric: "*float64", Float: "*float64", Float4: "*float64", Float8: "*float64", Double: "*float64", Real: "*float64", Bool: "*bool", Boolean: "*bool", } func main() { var name string flag.StringVar(&name, "name", "", "输入需要序列化的ddl文件名, 不需要后缀.ddl") flag.Parse() p, err := filepath.Abs(fmt.Sprintf("%s/%s.sql", targerDir, name)) if err != nil { panic(err) } ddlf, err := os.Open(p) if err != nil { panic(err) } ddlfilestr, err := ioutil.ReadAll(ddlf) if err != nil { panic(err) } // PRIMARY KEY (`guest_id`) USING BTREE re := regexp.MustCompile("PRIMARY\\s+KEY\\s+\\(\\s*`([^`]+)`\\s*\\)|`([^`]+)` [^\n]+PRIMARY\\s+KEY\\s+") matches := re.FindStringSubmatch(string(ddlfilestr)) PrimaryStr := "" if len(matches) > 0 { PrimaryStr = matches[1] } // 匹配到主键定义 parser.NewParser() result, err := parser.NewParser().From(p) if err != nil { panic(err) } fcontent := "package model\nimport \"gorm.io/gorm\"\n" for _, table := range result { structstr := "type %s struct {%s\n}\n" tableName := toPascalCase(table.Name) fieldstr := "" for _, col := range table.Columns { fieldName := toPascalCase(col.Name) typeName := SQLTypeToGoTypeMap[col.DataType.Type()] tagstr := "`gorm:" if col.Name == PrimaryStr { tagstr += "\"primary_key\"" typeName = typeName[1:] } else { tagstr += "\"\"" } tagstr += fmt.Sprintf(" json:\"%s\"`", col.Name) fieldColStr := fmt.Sprintf("\n%s %s %s// %s", fieldName, typeName, tagstr, col.Constraint.Comment) fieldstr += fieldColStr } fcontent += fmt.Sprintf(structstr, tableName, fieldstr) modelstr := fmt.Sprintf(`type %sModel struct {db *gorm.DB}`, tableName) fcontent += modelstr fcontent += "\n" newfuncstr := fmt.Sprintf(`func New%sModel(db *gorm.DB) *%sModel {return &%sModel{db}}`, tableName, tableName, tableName) fcontent += newfuncstr fcontent += "\n" genGoFileName := fmt.Sprintf("%s/%s_gen.go", genDir, table.Name) f, err := os.OpenFile(genGoFileName, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) if err != nil { panic(err) } f.WriteString(fcontent) err = f.Close() if err != nil { panic(err) } err = exec.Command("gofmt", "-w", genGoFileName).Run() if err != nil { panic(err) } // log.Println(fcontent) } }