|
|
|
package command
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/go-sql-driver/mysql"
|
|
|
|
"github.com/urfave/cli"
|
|
|
|
"github.com/zeromicro/go-zero/core/logx"
|
|
|
|
"github.com/zeromicro/go-zero/core/stores/postgres"
|
|
|
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
|
|
|
"github.com/zeromicro/go-zero/tools/goctl/config"
|
|
|
|
"github.com/zeromicro/go-zero/tools/goctl/model/sql/gen"
|
|
|
|
"github.com/zeromicro/go-zero/tools/goctl/model/sql/model"
|
|
|
|
"github.com/zeromicro/go-zero/tools/goctl/model/sql/util"
|
|
|
|
file "github.com/zeromicro/go-zero/tools/goctl/util"
|
|
|
|
"github.com/zeromicro/go-zero/tools/goctl/util/console"
|
|
|
|
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
flagSrc = "src"
|
|
|
|
flagDir = "dir"
|
|
|
|
flagCache = "cache"
|
|
|
|
flagIdea = "idea"
|
|
|
|
flagURL = "url"
|
|
|
|
flagTable = "table"
|
|
|
|
flagStyle = "style"
|
|
|
|
flagDatabase = "database"
|
|
|
|
flagSchema = "schema"
|
|
|
|
flagHome = "home"
|
|
|
|
)
|
|
|
|
|
|
|
|
var errNotMatched = errors.New("sql not matched")
|
|
|
|
|
|
|
|
// MysqlDDL generates model code from ddl
|
|
|
|
func MysqlDDL(ctx *cli.Context) error {
|
|
|
|
src := ctx.String(flagSrc)
|
|
|
|
dir := ctx.String(flagDir)
|
|
|
|
cache := ctx.Bool(flagCache)
|
|
|
|
idea := ctx.Bool(flagIdea)
|
|
|
|
style := ctx.String(flagStyle)
|
|
|
|
database := ctx.String(flagDatabase)
|
|
|
|
home := ctx.String(flagHome)
|
|
|
|
remote := ctx.String("remote")
|
|
|
|
if len(remote) > 0 {
|
|
|
|
repo, _ := file.CloneIntoGitHome(remote)
|
|
|
|
if len(repo) > 0 {
|
|
|
|
home = repo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(home) > 0 {
|
|
|
|
pathx.RegisterGoctlHome(home)
|
|
|
|
}
|
|
|
|
cfg, err := config.NewConfig(style)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return fromDDL(src, dir, cfg, cache, idea, database)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MySqlDataSource generates model code from datasource
|
|
|
|
func MySqlDataSource(ctx *cli.Context) error {
|
|
|
|
url := strings.TrimSpace(ctx.String(flagURL))
|
|
|
|
dir := strings.TrimSpace(ctx.String(flagDir))
|
|
|
|
cache := ctx.Bool(flagCache)
|
|
|
|
idea := ctx.Bool(flagIdea)
|
|
|
|
style := ctx.String(flagStyle)
|
|
|
|
home := ctx.String("home")
|
|
|
|
remote := ctx.String("remote")
|
|
|
|
if len(remote) > 0 {
|
|
|
|
repo, _ := file.CloneIntoGitHome(remote)
|
|
|
|
if len(repo) > 0 {
|
|
|
|
home = repo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(home) > 0 {
|
|
|
|
pathx.RegisterGoctlHome(home)
|
|
|
|
}
|
|
|
|
|
|
|
|
pattern := strings.TrimSpace(ctx.String(flagTable))
|
|
|
|
cfg, err := config.NewConfig(style)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return fromMysqlDataSource(url, pattern, dir, cfg, cache, idea)
|
|
|
|
}
|
|
|
|
|
|
|
|
// PostgreSqlDataSource generates model code from datasource
|
|
|
|
func PostgreSqlDataSource(ctx *cli.Context) error {
|
|
|
|
url := strings.TrimSpace(ctx.String(flagURL))
|
|
|
|
dir := strings.TrimSpace(ctx.String(flagDir))
|
|
|
|
cache := ctx.Bool(flagCache)
|
|
|
|
idea := ctx.Bool(flagIdea)
|
|
|
|
style := ctx.String(flagStyle)
|
|
|
|
schema := ctx.String(flagSchema)
|
|
|
|
home := ctx.String("home")
|
|
|
|
remote := ctx.String("remote")
|
|
|
|
if len(remote) > 0 {
|
|
|
|
repo, _ := file.CloneIntoGitHome(remote)
|
|
|
|
if len(repo) > 0 {
|
|
|
|
home = repo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(home) > 0 {
|
|
|
|
pathx.RegisterGoctlHome(home)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(schema) == 0 {
|
|
|
|
schema = "public"
|
|
|
|
}
|
|
|
|
|
|
|
|
pattern := strings.TrimSpace(ctx.String(flagTable))
|
|
|
|
cfg, err := config.NewConfig(style)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return fromPostgreSqlDataSource(url, pattern, dir, schema, cfg, cache, idea)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fromDDL(src, dir string, cfg *config.Config, cache, idea bool, database string) error {
|
|
|
|
log := console.NewConsole(idea)
|
|
|
|
src = strings.TrimSpace(src)
|
|
|
|
if len(src) == 0 {
|
|
|
|
return errors.New("expected path or path globbing patterns, but nothing found")
|
|
|
|
}
|
|
|
|
|
|
|
|
files, err := util.MatchFiles(src)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(files) == 0 {
|
|
|
|
return errNotMatched
|
|
|
|
}
|
|
|
|
|
|
|
|
generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, file := range files {
|
|
|
|
err = generator.StartFromDDL(file, cache, database)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func fromMysqlDataSource(url, pattern, dir string, cfg *config.Config, cache, idea bool) error {
|
|
|
|
log := console.NewConsole(idea)
|
|
|
|
if len(url) == 0 {
|
|
|
|
log.Error("%v", "expected data source of mysql, but nothing found")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(pattern) == 0 {
|
|
|
|
log.Error("%v", "expected table or table globbing patterns, but nothing found")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
dsn, err := mysql.ParseDSN(url)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
logx.Disable()
|
|
|
|
databaseSource := strings.TrimSuffix(url, "/"+dsn.DBName) + "/information_schema"
|
|
|
|
db := sqlx.NewMysql(databaseSource)
|
|
|
|
im := model.NewInformationSchemaModel(db)
|
|
|
|
|
|
|
|
tables, err := im.GetAllTables(dsn.DBName)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
matchTables := make(map[string]*model.Table)
|
|
|
|
for _, item := range tables {
|
|
|
|
match, err := filepath.Match(pattern, item)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !match {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
columnData, err := im.FindColumns(dsn.DBName, item)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
table, err := columnData.Convert()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
matchTables[item] = table
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(matchTables) == 0 {
|
|
|
|
return errors.New("no tables matched")
|
|
|
|
}
|
|
|
|
|
|
|
|
generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return generator.StartFromInformationSchema(matchTables, cache)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fromPostgreSqlDataSource(url, pattern, dir, schema string, cfg *config.Config, cache, idea bool) error {
|
|
|
|
log := console.NewConsole(idea)
|
|
|
|
if len(url) == 0 {
|
|
|
|
log.Error("%v", "expected data source of postgresql, but nothing found")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(pattern) == 0 {
|
|
|
|
log.Error("%v", "expected table or table globbing patterns, but nothing found")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
db := postgres.New(url)
|
|
|
|
im := model.NewPostgreSqlModel(db)
|
|
|
|
|
|
|
|
tables, err := im.GetAllTables(schema)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
matchTables := make(map[string]*model.Table)
|
|
|
|
for _, item := range tables {
|
|
|
|
match, err := filepath.Match(pattern, item)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !match {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
columnData, err := im.FindColumns(schema, item)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
table, err := columnData.Convert()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
matchTables[item] = table
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(matchTables) == 0 {
|
|
|
|
return errors.New("no tables matched")
|
|
|
|
}
|
|
|
|
|
|
|
|
generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log), gen.WithPostgreSql())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return generator.StartFromInformationSchema(matchTables, cache)
|
|
|
|
}
|