github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/gormgen/tools/gentool/gentool.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  	"strings"
     9  
    10  	"github.com/unionj-cloud/go-doudou/v2/toolkit/gormgen"
    11  	"gopkg.in/yaml.v3"
    12  	"gorm.io/driver/clickhouse"
    13  	"gorm.io/driver/mysql"
    14  	"gorm.io/driver/postgres"
    15  	"gorm.io/driver/sqlite"
    16  	"gorm.io/driver/sqlserver"
    17  	"gorm.io/gorm"
    18  )
    19  
    20  // DBType database type
    21  type DBType string
    22  
    23  const (
    24  	// dbMySQL Gorm Drivers mysql || postgres || sqlite || sqlserver
    25  	dbMySQL      DBType = "mysql"
    26  	dbPostgres   DBType = "postgres"
    27  	dbSQLite     DBType = "sqlite"
    28  	dbSQLServer  DBType = "sqlserver"
    29  	dbClickHouse DBType = "clickhouse"
    30  )
    31  
    32  // CmdParams is command line parameters
    33  type CmdParams struct {
    34  	DSN               string   `yaml:"dsn"`               // consult[https://gorm.io/docs/connecting_to_the_database.html]"
    35  	DB                string   `yaml:"db"`                // input mysql or postgres or sqlite or sqlserver. consult[https://gorm.io/docs/connecting_to_the_database.html]
    36  	Tables            []string `yaml:"tables"`            // enter the required data table or leave it blank
    37  	OnlyModel         bool     `yaml:"onlyModel"`         // only generate model
    38  	OutPath           string   `yaml:"outPath"`           // specify a directory for output
    39  	OutFile           string   `yaml:"outFile"`           // query code file name, default: gen.go
    40  	WithUnitTest      bool     `yaml:"withUnitTest"`      // generate unit test for query code
    41  	ModelPkgName      string   `yaml:"modelPkgName"`      // generated model code's package name
    42  	FieldNullable     bool     `yaml:"fieldNullable"`     // generate with pointer when field is nullable
    43  	FieldWithIndexTag bool     `yaml:"fieldWithIndexTag"` // generate field with gorm index tag
    44  	FieldWithTypeTag  bool     `yaml:"fieldWithTypeTag"`  // generate field with gorm column type tag
    45  	FieldSignable     bool     `yaml:"fieldSignable"`     // detect integer field's unsigned type, adjust generated data type
    46  }
    47  
    48  // YamlConfig is yaml config struct
    49  type YamlConfig struct {
    50  	Version  string     `yaml:"version"`  //
    51  	Database *CmdParams `yaml:"database"` //
    52  }
    53  
    54  // connectDB choose db type for connection to database
    55  func connectDB(t DBType, dsn string) (*gorm.DB, error) {
    56  	if dsn == "" {
    57  		return nil, fmt.Errorf("dsn cannot be empty")
    58  	}
    59  
    60  	switch t {
    61  	case dbMySQL:
    62  		return gorm.Open(mysql.Open(dsn))
    63  	case dbPostgres:
    64  		return gorm.Open(postgres.Open(dsn))
    65  	case dbSQLite:
    66  		return gorm.Open(sqlite.Open(dsn))
    67  	case dbSQLServer:
    68  		return gorm.Open(sqlserver.Open(dsn))
    69  	case dbClickHouse:
    70  		return gorm.Open(clickhouse.Open(dsn))
    71  	default:
    72  		return nil, fmt.Errorf("unknow db %q (support mysql || postgres || sqlite || sqlserver for now)", t)
    73  	}
    74  }
    75  
    76  // genModels is gorm/gen generated models
    77  func genModels(g *gormgen.Generator, db *gorm.DB, tables []string) (models []interface{}, err error) {
    78  	var tablesList []string
    79  	if len(tables) == 0 {
    80  		// Execute tasks for all tables in the database
    81  		tablesList, err = db.Migrator().GetTables()
    82  		if err != nil {
    83  			return nil, fmt.Errorf("GORM migrator get all tables fail: %w", err)
    84  		}
    85  	} else {
    86  		tablesList = tables
    87  	}
    88  
    89  	// Execute some data table tasks
    90  	models = make([]interface{}, len(tablesList))
    91  	for i, tableName := range tablesList {
    92  		models[i] = g.GenerateModel(tableName)
    93  	}
    94  	return models, nil
    95  }
    96  
    97  // loadConfigFile load config file from path
    98  func loadConfigFile(path string) (*CmdParams, error) {
    99  	file, err := os.Open(path)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	defer file.Close() // nolint
   104  	var yamlConfig YamlConfig
   105  	if cmdErr := yaml.NewDecoder(file).Decode(&yamlConfig); cmdErr != nil {
   106  		return nil, cmdErr
   107  	}
   108  	return yamlConfig.Database, nil
   109  }
   110  
   111  // argParse is parser for cmd
   112  func argParse() *CmdParams {
   113  	// choose is file or flag
   114  	genPath := flag.String("c", "", "is path for gen.yml")
   115  	dsn := flag.String("dsn", "", "consult[https://gorm.io/docs/connecting_to_the_database.html]")
   116  	db := flag.String("db", "mysql", "input mysql|postgres|sqlite|sqlserver|clickhouse. consult[https://gorm.io/docs/connecting_to_the_database.html]")
   117  	tableList := flag.String("tables", "", "enter the required data table or leave it blank")
   118  	onlyModel := flag.Bool("onlyModel", false, "only generate models (without query file)")
   119  	outPath := flag.String("outPath", "./dao/query", "specify a directory for output")
   120  	outFile := flag.String("outFile", "", "query code file name, default: gen.go")
   121  	withUnitTest := flag.Bool("withUnitTest", false, "generate unit test for query code")
   122  	modelPkgName := flag.String("modelPkgName", "", "generated model code's package name")
   123  	fieldNullable := flag.Bool("fieldNullable", false, "generate with pointer when field is nullable")
   124  	fieldWithIndexTag := flag.Bool("fieldWithIndexTag", false, "generate field with gorm index tag")
   125  	fieldWithTypeTag := flag.Bool("fieldWithTypeTag", false, "generate field with gorm column type tag")
   126  	fieldSignable := flag.Bool("fieldSignable", false, "detect integer field's unsigned type, adjust generated data type")
   127  	flag.Parse()
   128  	var cmdParse CmdParams
   129  	if *genPath != "" {
   130  		if configFileParams, err := loadConfigFile(*genPath); err == nil && configFileParams != nil {
   131  			cmdParse = *configFileParams
   132  		} else if err != nil {
   133  			log.Fatalf("loadConfigFile fail %s", err.Error())
   134  		}
   135  	}
   136  	// cmd first
   137  	if *dsn != "" {
   138  		cmdParse.DSN = *dsn
   139  	}
   140  	if *db != "" {
   141  		cmdParse.DB = *db
   142  	}
   143  	if *tableList != "" {
   144  		cmdParse.Tables = strings.Split(*tableList, ",")
   145  	}
   146  	if *onlyModel {
   147  		cmdParse.OnlyModel = true
   148  	}
   149  	if *outPath != "" {
   150  		cmdParse.OutPath = *outPath
   151  	}
   152  	if *outFile != "" {
   153  		cmdParse.OutFile = *outFile
   154  	}
   155  	if *withUnitTest {
   156  		cmdParse.WithUnitTest = *withUnitTest
   157  	}
   158  	if *modelPkgName != "" {
   159  		cmdParse.ModelPkgName = *modelPkgName
   160  	}
   161  	if *fieldNullable {
   162  		cmdParse.FieldNullable = *fieldNullable
   163  	}
   164  	if *fieldWithIndexTag {
   165  		cmdParse.FieldWithIndexTag = *fieldWithIndexTag
   166  	}
   167  	if *fieldWithTypeTag {
   168  		cmdParse.FieldWithTypeTag = *fieldWithTypeTag
   169  	}
   170  	if *fieldSignable {
   171  		cmdParse.FieldSignable = *fieldSignable
   172  	}
   173  	return &cmdParse
   174  }
   175  
   176  func main() {
   177  	// cmdParse
   178  	config := argParse()
   179  	if config == nil {
   180  		log.Fatalln("parse config fail")
   181  	}
   182  	db, err := connectDB(DBType(config.DB), config.DSN)
   183  	if err != nil {
   184  		log.Fatalln("connect db server fail:", err)
   185  	}
   186  
   187  	g := gormgen.NewGenerator(gormgen.Config{
   188  		OutPath:           config.OutPath,
   189  		OutFile:           config.OutFile,
   190  		ModelPkgPath:      config.ModelPkgName,
   191  		WithUnitTest:      config.WithUnitTest,
   192  		FieldNullable:     config.FieldNullable,
   193  		FieldWithIndexTag: config.FieldWithIndexTag,
   194  		FieldWithTypeTag:  config.FieldWithTypeTag,
   195  		FieldSignable:     config.FieldSignable,
   196  	})
   197  
   198  	g.UseDB(db)
   199  
   200  	models, err := genModels(g, db, config.Tables)
   201  	if err != nil {
   202  		log.Fatalln("get tables info fail:", err)
   203  	}
   204  
   205  	if !config.OnlyModel {
   206  		g.ApplyBasic(models...)
   207  	}
   208  
   209  	g.Execute()
   210  }