Skip to content

Commit

Permalink
generate models
Browse files Browse the repository at this point in the history
  • Loading branch information
Khang Ha committed Oct 6, 2020
1 parent eeca5c7 commit 7ab11d3
Show file tree
Hide file tree
Showing 19 changed files with 587 additions and 11 deletions.
103 changes: 103 additions & 0 deletions adapters/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package database

import (
"database/sql"
"time"

"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/plugin/dbresolver"
)

// Errs alias
var (
ErrRecordNotFound = gorm.ErrRecordNotFound
)

// DBAdapter interface represent adapter connect to DB
type DBAdapter interface {
Open(string) error
Close()
Begin() DBAdapter
RollbackUselessCommitted()
Commit()
Gormer() *gorm.DB
DB() *sql.DB
}

type adapter struct {
gormer *gorm.DB
isCommitted bool
}

// NewDB returns a new instance of DB.
func NewDB() DBAdapter {
return &adapter{}
}

// Open opens a DB connection.
func (db *adapter) Open(connectionString string) error {
//newLogger := logger.New(
// log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
// logger.Config{
// SlowThreshold: time.Second, // Slow SQL threshold
// LogLevel: logger.Info, // Log level
// Colorful: true, // Disable color
// },
//)

gormDB, err := gorm.Open(mysql.Open(connectionString), &gorm.Config{})
if err != nil {
return err
}
db.gormer = gormDB

gormDB.Use(
dbresolver.Register(dbresolver.Config{ /* xxx */ }).
SetConnMaxIdleTime(time.Hour).
SetConnMaxLifetime(24 * time.Hour).
SetMaxIdleConns(100).
SetMaxOpenConns(200),
)
return nil
}

// Close closes DB connection.
func (db *adapter) Close() {
_ = db.DB().Close()
}

// Begin starts a DB transaction.
func (db *adapter) Begin() DBAdapter {
tx := db.gormer.Begin()
return &adapter{
gormer: tx,
isCommitted: false,
}
}

// RollbackUselessCommitted rollbacks useless DB transaction committed.
func (db *adapter) RollbackUselessCommitted() {
if !db.isCommitted {
db.gormer.Rollback()
}
}

// Commit commits a DB transaction.
func (db *adapter) Commit() {
if !db.isCommitted {
db.gormer.Commit()
db.isCommitted = true
}
}

// Gormer returns an instance of gorm.DB.
func (db *adapter) Gormer() *gorm.DB {
return db.gormer
}

// DB returns an instance of sql.DB.
func (db *adapter) DB() *sql.DB {
database, _ := db.gormer.DB()
return database
}
131 changes: 131 additions & 0 deletions cmd/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package cmd

import (
"fmt"
"os"
"strings"

database "github.com/khanghldk/gokit/adapters"
"github.com/khanghldk/gokit/configs"
"github.com/khanghldk/gokit/constants"
"github.com/khanghldk/gokit/models"
"github.com/khanghldk/gokit/repositories"
"github.com/khanghldk/gokit/templates"
"github.com/khanghldk/gokit/utils"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

// genModelCmd represents the new command
var genModelsCmd = &cobra.Command{
Use: "models",
Aliases: []string{"m"},
Short: "Generate models from database",
Run: func(cmd *cobra.Command, args []string) {
fmt.Print(constants.ColorBlue, "Generate models...\n")

dir := "models"

os.Mkdir(dir, os.ModePerm)

db := database.NewDB()
if err := db.Open(configs.AppConfig.DB.ConnectionString()); err != nil {
logrus.Fatalf("Creating connection to DB: %v", err)
}

schema := repositories.NewSchema(db)
tables, err := schema.GetTables()
if err != nil {
logrus.Fatalf("error: %v", err)
}

for i := range tables {
if tables[i] == "migrations" {
continue
}
columns, err := schema.GetColumns(tables[i])
if err != nil {
logrus.Errorf("Get columns of table %v got error %v", tables[i], err)
} else {
fmt.Println("Creating model", utils.Camel(tables[i], false), "...")
createModel(columns, dir, tables[i])
}
}

utils.GoFmt(dir)
fmt.Println("Finish generating models")
},
}

func createModel(columns []*models.MySQLColumn, dir, tableName string) {
fileName := fmt.Sprintf("./models/%v.go", utils.Snake(tableName))
columnsRaw := ""

for i := 0; i < len(columns); i++ {
column := templates.ColumnTemplate
columnNameCamel := utils.Camel(columns[i].ColumnName, false)
dataType := getDataType(columns[i].ColumnType)

column = standardizedColumn(column, columnNameCamel, dataType)
columnsRaw += fmt.Sprintf("\n%v", column)
}

model := strings.ReplaceAll(templates.ModelTemplate, constants.ModelContent, columnsRaw)
model = strings.ReplaceAll(model, constants.ModelNameLower, utils.Camel(tableName, false))
err := utils.CreateFile(fileName, []byte(model))
if err != nil {
logrus.Fatal(err)
}
}

func standardizedColumn(column, columnNameCamel, dataType string) string {
column = strings.ReplaceAll(column, constants.ColumnName, columnNameCamel)
column = strings.ReplaceAll(column, constants.ColumnType, dataType)
return column
}

func getDataType(sqlType string) string {
if strings.Contains(sqlType, constants.Tinyint) {
return constants.Bool
}

if strings.Contains(sqlType, constants.Int) ||
strings.Contains(sqlType, constants.Bigint) ||
strings.Contains(sqlType, constants.Smallint) {
return constants.Int64
}

if strings.Contains(sqlType, constants.Varchar) ||
strings.Contains(sqlType, constants.Text) ||
strings.Contains(sqlType, constants.Longtext) {
return constants.String
}

if strings.Contains(sqlType, constants.Double) {
return constants.Float64
}

if strings.Contains(sqlType, constants.DateTime) ||
strings.Contains(sqlType, constants.Timestamp) {
return constants.Time
}

if strings.Contains(sqlType, constants.Json) {
return constants.JSON
}

if strings.Contains(sqlType, constants.Enum) {
return "enum"
}

return "undefined"
}

func init() {
_, err := configs.New()
if err != nil {
os.Exit(99)
}

RootCmd.AddCommand(genModelsCmd)
}
43 changes: 43 additions & 0 deletions configs/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package configs

import (
"fmt"

"github.com/kelseyhightower/envconfig"
)

// Package constants definition.
const (
Prefix = ""
)

// App represents all configuration of qr-service application.
type App struct {
DB MySQL
}

// MySQL represents configuration of MySQL database.
type MySQL struct {
Username string `default:"root" envconfig:"MYSQL_USER"`
Password string `default:"root" envconfig:"MYSQL_PASS"`
Host string `default:"127.0.0.1" envconfig:"MYSQL_HOST"`
Port int `default:"3306" envconfig:"MYSQL_PORT"`
Database string `default:"evoucher_service" envconfig:"MYSQL_DB"`
}

// ConnectionString returns connection string of MySQL database.
func (c *MySQL) ConnectionString() string {
format := "%v:%v@tcp(%v:%v)/%v?parseTime=true&charset=utf8"
return fmt.Sprintf(format, c.Username, c.Password, c.Host, c.Port, c.Database) + "&loc=Asia%2FHo_Chi_Minh"
}

// AppConfig is addition config for gami-service
var AppConfig App

// New returns a new instance of playground configuration.
func New() (*App, error) {
if err := envconfig.Process(Prefix, &AppConfig); err != nil {
return nil, err
}
return &AppConfig, nil
}
2 changes: 1 addition & 1 deletion constants/colors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package constants

// Color Constants
const (
ColorReset = "\033[0m"
ColorReset = "\033[0m"
ColorRed = "\033[31m"
ColorGreen = "\033[32m"
ColorYellow = "\033[33m"
Expand Down
35 changes: 35 additions & 0 deletions constants/def.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package constants

import (
"gorm.io/datatypes"
)

// Definition constants
const (
ModuleName = "MODULE_NAME"
Expand All @@ -11,8 +15,39 @@ const (
ServiceNameLower = "service_name"
RepositoryName = "REPOSITORY_NAME"
RepositoryNameLower = "repository_name"
ModelNameLower = "model_name"
ModelContent = "MODEL_CONTENT"
ColumnName = "COLUMN_NAME"
ColumnNameLower = "column_name"
ColumnType = "column_type"

Space = " "
Underscore = "_"
EmptyString = ""

// MySQLDataTypes
DateTime = "datetime"
Varchar = "varchar"
Bigint = "bigint"
Longtext = "longtext"
Tinyint = "tinyint"
Int = "int"
Enum = "enum"
Smallint = "smallint"
Double = "double"
Json = "json"
Timestamp = "timestamp"
Text = "text"

// GolangTypes
Int64 = "int64"
Bool = "bool"
String = "string"
Time = "time.Time"
Float64 = "float64"
JSON = "datatypes.JSON"
)

type Test struct {
JSON datatypes.JSON
}
2 changes: 1 addition & 1 deletion constants/version.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package constants

// Version ...
const Version = "v0.0.6"
const Version = "v0.0.10"
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ module github.com/khanghldk/gokit
go 1.15

require (
github.com/kelseyhightower/envconfig v1.4.0
github.com/pelletier/go-toml v1.8.0 // indirect
github.com/sirupsen/logrus v1.6.0
github.com/spf13/cobra v1.0.0
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.4.0 // indirect
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
gorm.io/datatypes v0.0.0-20200806042100-bc394008dd0d
gorm.io/driver/mysql v1.0.1
gorm.io/gorm v1.20.1
gorm.io/plugin/dbresolver v1.0.0
)
Loading

0 comments on commit 7ab11d3

Please sign in to comment.