123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- package command
- import (
- "errors"
- "path/filepath"
- "strings"
- "github.com/go-sql-driver/mysql"
- "github.com/spf13/cobra"
- "github.com/wuntsong-org/go-zero-plus/core/collection"
- "github.com/wuntsong-org/go-zero-plus/core/logx"
- "github.com/wuntsong-org/go-zero-plus/core/stores/postgres"
- "github.com/wuntsong-org/go-zero-plus/core/stores/sqlx"
- "github.com/wuntsong-org/go-zero-plus/tools/goctlwt/config"
- "github.com/wuntsong-org/go-zero-plus/tools/goctlwt/model/sql/command/migrationnotes"
- "github.com/wuntsong-org/go-zero-plus/tools/goctlwt/model/sql/gen"
- "github.com/wuntsong-org/go-zero-plus/tools/goctlwt/model/sql/model"
- "github.com/wuntsong-org/go-zero-plus/tools/goctlwt/model/sql/util"
- file "github.com/wuntsong-org/go-zero-plus/tools/goctlwt/util"
- "github.com/wuntsong-org/go-zero-plus/tools/goctlwt/util/console"
- "github.com/wuntsong-org/go-zero-plus/tools/goctlwt/util/pathx"
- )
- var (
- // VarStringSrc describes the source file of sql.
- VarStringSrc string
- // VarStringDir describes the output directory of sql.
- VarStringDir string
- // VarBoolCache describes whether the cache is enabled.
- VarBoolCache bool
- // VarBoolIdea describes whether is idea or not.
- VarBoolIdea bool
- // VarStringURL describes the dsn of the sql.
- VarStringURL string
- // VarStringSliceTable describes tables.
- VarStringSliceTable []string
- // VarStringStyle describes the style.
- VarStringStyle string
- // VarStringDatabase describes the database.
- VarStringDatabase string
- // VarStringSchema describes the schema of postgresql.
- VarStringSchema string
- // VarStringHome describes the goctl home.
- VarStringHome string
- // VarStringRemote describes the remote git repository.
- VarStringRemote string
- // VarStringBranch describes the git branch of the repository.
- VarStringBranch string
- // VarBoolStrict describes whether the strict mode is enabled.
- VarBoolStrict bool
- // VarStringSliceIgnoreColumns represents the columns which are ignored.
- VarStringSliceIgnoreColumns []string
- )
- var errNotMatched = errors.New("sql not matched")
- // MysqlDDL generates model code from ddl
- func MysqlDDL(_ *cobra.Command, _ []string) error {
- migrationnotes.BeforeCommands(VarStringDir, VarStringStyle)
- src := VarStringSrc
- dir := VarStringDir
- cache := VarBoolCache
- idea := VarBoolIdea
- style := VarStringStyle
- database := VarStringDatabase
- home := VarStringHome
- remote := VarStringRemote
- branch := VarStringBranch
- if len(remote) > 0 {
- repo, _ := file.CloneIntoGitHome(remote, branch)
- if len(repo) > 0 {
- home = repo
- }
- }
- if len(home) > 0 {
- pathx.RegisterGoctlHome(home)
- }
- cfg, err := config.NewConfig(style)
- if err != nil {
- return err
- }
- arg := ddlArg{
- src: src,
- dir: dir,
- cfg: cfg,
- cache: cache,
- idea: idea,
- database: database,
- strict: VarBoolStrict,
- ignoreColumns: mergeColumns(VarStringSliceIgnoreColumns),
- }
- return fromDDL(arg)
- }
- // MySqlDataSource generates model code from datasource
- func MySqlDataSource(_ *cobra.Command, _ []string) error {
- migrationnotes.BeforeCommands(VarStringDir, VarStringStyle)
- url := strings.TrimSpace(VarStringURL)
- dir := strings.TrimSpace(VarStringDir)
- cache := VarBoolCache
- idea := VarBoolIdea
- style := VarStringStyle
- home := VarStringHome
- remote := VarStringRemote
- branch := VarStringBranch
- if len(remote) > 0 {
- repo, _ := file.CloneIntoGitHome(remote, branch)
- if len(repo) > 0 {
- home = repo
- }
- }
- if len(home) > 0 {
- pathx.RegisterGoctlHome(home)
- }
- tableValue := VarStringSliceTable
- patterns := parseTableList(tableValue)
- cfg, err := config.NewConfig(style)
- if err != nil {
- return err
- }
- arg := dataSourceArg{
- url: url,
- dir: dir,
- tablePat: patterns,
- cfg: cfg,
- cache: cache,
- idea: idea,
- strict: VarBoolStrict,
- ignoreColumns: mergeColumns(VarStringSliceIgnoreColumns),
- }
- return fromMysqlDataSource(arg)
- }
- func mergeColumns(columns []string) []string {
- set := collection.NewSet()
- for _, v := range columns {
- fields := strings.FieldsFunc(v, func(r rune) bool {
- return r == ','
- })
- set.AddStr(fields...)
- }
- return set.KeysStr()
- }
- type pattern map[string]struct{}
- func (p pattern) Match(s string) bool {
- for v := range p {
- match, err := filepath.Match(v, s)
- if err != nil {
- console.Error("%+v", err)
- continue
- }
- if match {
- return true
- }
- }
- return false
- }
- func (p pattern) list() []string {
- var ret []string
- for v := range p {
- ret = append(ret, v)
- }
- return ret
- }
- func parseTableList(tableValue []string) pattern {
- tablePattern := make(pattern)
- for _, v := range tableValue {
- fields := strings.FieldsFunc(v, func(r rune) bool {
- return r == ','
- })
- for _, f := range fields {
- tablePattern[f] = struct{}{}
- }
- }
- return tablePattern
- }
- // PostgreSqlDataSource generates model code from datasource
- func PostgreSqlDataSource(_ *cobra.Command, _ []string) error {
- migrationnotes.BeforeCommands(VarStringDir, VarStringStyle)
- url := strings.TrimSpace(VarStringURL)
- dir := strings.TrimSpace(VarStringDir)
- cache := VarBoolCache
- idea := VarBoolIdea
- style := VarStringStyle
- schema := VarStringSchema
- home := VarStringHome
- remote := VarStringRemote
- branch := VarStringBranch
- if len(remote) > 0 {
- repo, _ := file.CloneIntoGitHome(remote, branch)
- if len(repo) > 0 {
- home = repo
- }
- }
- if len(home) > 0 {
- pathx.RegisterGoctlHome(home)
- }
- if len(schema) == 0 {
- schema = "public"
- }
- patterns := parseTableList(VarStringSliceTable)
- cfg, err := config.NewConfig(style)
- if err != nil {
- return err
- }
- ignoreColumns := mergeColumns(VarStringSliceIgnoreColumns)
- return fromPostgreSqlDataSource(url, patterns, dir, schema, cfg, cache, idea, VarBoolStrict, ignoreColumns)
- }
- type ddlArg struct {
- src, dir string
- cfg *config.Config
- cache, idea bool
- database string
- strict bool
- ignoreColumns []string
- }
- func fromDDL(arg ddlArg) error {
- log := console.NewConsole(arg.idea)
- src := strings.TrimSpace(arg.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(arg.dir, arg.cfg,
- gen.WithConsoleOption(log), gen.WithIgnoreColumns(arg.ignoreColumns))
- if err != nil {
- return err
- }
- for _, file := range files {
- err = generator.StartFromDDL(file, arg.cache, arg.strict, arg.database)
- if err != nil {
- return err
- }
- }
- return nil
- }
- type dataSourceArg struct {
- url, dir string
- tablePat pattern
- cfg *config.Config
- cache, idea bool
- strict bool
- ignoreColumns []string
- }
- func fromMysqlDataSource(arg dataSourceArg) error {
- log := console.NewConsole(arg.idea)
- if len(arg.url) == 0 {
- log.Error("%v", "expected data source of mysql, but nothing found")
- return nil
- }
- if len(arg.tablePat) == 0 {
- log.Error("%v", "expected table or table globbing patterns, but nothing found")
- return nil
- }
- dsn, err := mysql.ParseDSN(arg.url)
- if err != nil {
- return err
- }
- logx.Disable()
- databaseSource := strings.TrimSuffix(arg.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 {
- if !arg.tablePat.Match(item) {
- 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(arg.dir, arg.cfg,
- gen.WithConsoleOption(log), gen.WithIgnoreColumns(arg.ignoreColumns))
- if err != nil {
- return err
- }
- return generator.StartFromInformationSchema(matchTables, arg.cache, arg.strict)
- }
- func fromPostgreSqlDataSource(url string, pattern pattern, dir, schema string, cfg *config.Config, cache, idea, strict bool, ignoreColumns []string) 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 {
- if !pattern.Match(item) {
- 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(), gen.WithIgnoreColumns(ignoreColumns))
- if err != nil {
- return err
- }
- return generator.StartFromInformationSchema(matchTables, cache, strict)
- }
|