李伟乐 1 year ago
parent d292f0c23d
commit 6df063ffcc
  1. 1
      cmd/mysql-kit/core/funcs.go
  2. 35
      cmd/mysql-kit/core/template.go
  3. 48
      cmd/mysql-kit/core/vars.go
  4. 18
      cmd/mysql-kit/custom.tpl
  5. 81
      cmd/mysql-kit/main.go
  6. 42
      cmd/mysql-kit/template.tpl
  7. 7
      errors/sqlerror.go
  8. 47
      mysql/builder/builder.go
  9. 23
      mysql/builder/builder_test.go
  10. 0
      pathx/a.txt
  11. 13
      pathx/file.go
  12. 11
      pathx/file_test.go
  13. 14
      stringx/stringx.go
  14. 11
      stringx/stringx_test.go
  15. 22
      tools/model/cmd.go
  16. 1
      tools/model/sql/command/command.go
  17. 11
      tools/model/sql/gen/d/main.go
  18. 52
      tools/model/sql/gen/gen.go
  19. 71
      tools/model/sql/gen/parser/parser.go

@ -0,0 +1,35 @@
package core
import (
"fmt"
"git.diulo.com/mogfee/kit/mysql/ddl"
"git.diulo.com/mogfee/kit/stringx"
"html/template"
"io"
"strings"
)
func SaveFile(w io.Writer, templateContent string, table *ddl.Table) error {
tmp, err := template.New("").Funcs(map[string]any{
"UpperType": func(str string) string {
return stringx.Ucfirst(ddl.GoName(str))
},
"LowerType": func(str string) string {
if str == "type" {
str = "vtype"
}
return stringx.Lcfirst(ddl.GoName(str))
},
"UpdateColumn": func(columns []*ddl.TableColumn) string {
arr := []string{}
for _, v := range columns {
arr = append(arr, fmt.Sprintf("%s=?", v.Name))
}
return strings.Join(arr, " and ")
},
}).Parse(templateContent)
if err != nil {
return err
}
return tmp.Execute(w, table)
}

@ -0,0 +1,48 @@
package core
import (
"fmt"
"os"
"strings"
)
func VarsFile(savePath string) error {
saveFileName := fmt.Sprintf("%s/vars.go", strings.TrimRight(savePath, "/"))
return os.WriteFile(saveFileName, []byte(`
package model
import (
"git.diulo.com/mogfee/kit/errors"
"gorm.io/gorm"
)
var ErrNotFound = errors.BadRequest("DB_NOT_FOUND", "数据不存在")
var ErrIdRequest = errors.BadRequest("DB_ID_REQUIRED", "id不能为空")
func IsErrNotFound(err error) bool {
return errors.Reason(err) == "DB_NOT_FOUND"
}
func IsErrIdRequest(err error) bool {
return errors.Reason(err) == "DB_ID_REQUIRED"
}
func findResultWithError[T any](data T, err error) (T, error) {
switch err {
case nil:
return data, nil
case gorm.ErrRecordNotFound:
return data, ErrNotFound
default:
return data, err
}
}
func GetPage(page int32, size int32) (offset int, pageSize int) {
if page <= 1 {
page = 1
}
offset = int((page - 1) * size)
return offset, int(size)
}
`), os.ModePerm)
}

@ -0,0 +1,18 @@
package model
import "gorm.io/gorm"
type (
{{$.Name|UpperType}}Model interface {
{{$.Name|LowerType}}Model
}
custom{{$.Name|UpperType}}Model struct {
*default{{$.Name|UpperType}}Model
}
)
func New{{$.Name|UpperType}}Model(db *gorm.DB) {{$.Name|UpperType}}Model {
return &custom{{$.Name|UpperType}}Model{
default{{$.Name|UpperType}}Model: new{{$.Name|UpperType}}DAO(db),
}
}

@ -4,20 +4,23 @@ import (
_ "embed" _ "embed"
"flag" "flag"
"fmt" "fmt"
"git.diulo.com/mogfee/kit/cmd/mysql-kit/core"
"git.diulo.com/mogfee/kit/mysql/ddl" "git.diulo.com/mogfee/kit/mysql/ddl"
"git.diulo.com/mogfee/kit/stringx" "git.diulo.com/mogfee/kit/pathx"
"html/template"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
) )
//go:embed template.tpl //go:embed template.tpl
var modelTemplate string var templateContent string
//go:embed custom.tpl
var customContent string
func main() { func main() {
sqlFile := flag.String("f", "", "数据库创建mysqldump文件") sqlFile := flag.String("f", "/Users/mogfee/web/sendmail_server_new/test_gozero.sql", "数据库创建mysqldump文件")
savePath := flag.String("s", "./model/", "数据库存储路径") savePath := flag.String("s", "./model", "数据库存储路径")
flag.Parse() flag.Parse()
fmt.Println("sqlfile:", *sqlFile) fmt.Println("sqlfile:", *sqlFile)
fmt.Println("savePath:", *savePath) fmt.Println("savePath:", *savePath)
@ -25,46 +28,58 @@ func main() {
return return
} }
os.MkdirAll(*savePath, os.ModePerm) os.MkdirAll(*savePath, os.ModePerm)
if err := core.VarsFile(*savePath); err != nil {
panic(err)
}
err := ddl.Parser(*sqlFile, func(table *ddl.Table) error { err := ddl.Parser(*sqlFile, func(table *ddl.Table) error {
//table.Imports = append(table.Imports, "git.diulo.com/mogfee/kit/errors")
//modelFileName := fmt.Sprintf("%s/%s_model_gen.go", strings.TrimRight(*savePath, "/"), table.Name)
modelGenFile := fmt.Sprintf("%s/%smodel_gen.go", strings.TrimRight(*savePath, "/"), filename(table.Name))
modelFile := fmt.Sprintf("%s/%smodel.go", strings.TrimRight(*savePath, "/"), filename(table.Name))
table.Imports = append(table.Imports, "gorm.io/gorm") table.Imports = append(table.Imports, "gorm.io/gorm")
table.Imports = append(table.Imports, "context") table.Imports = append(table.Imports, "context")
//table.Imports = append(table.Imports, "git.diulo.com/mogfee/kit/errors")
saveFileName := fmt.Sprintf("%s/%s_gen.go", strings.TrimRight(*savePath, "/"), table.Name) table.Indexes = filterIndex(table.Indexes)
tmp, err := template.New("").Funcs(map[string]any{
"UpperType": func(str string) string { if err := saveFile(modelGenFile, templateContent, table, false); err != nil {
return stringx.Ucfirst(ddl.GoName(str))
},
"LowerType": func(str string) string {
if str == "type" {
str = "vtype"
}
return stringx.Lcfirst(ddl.GoName(str))
},
"UpdateColumn": func(columns []*ddl.TableColumn) string {
arr := []string{}
for _, v := range columns {
arr = append(arr, fmt.Sprintf("%s=?", v.Name))
}
return strings.Join(arr, " and ")
},
}).Parse(modelTemplate)
if err != nil {
return err return err
} }
//ddl.PrintJson(table)
//table.Primary.GoType if err := saveFile(modelFile, customContent, table, true); err != nil {
//fmt.Println(table.Primary)
f, err := os.Create(saveFileName)
if err != nil {
return err return err
} }
defer f.Close() return nil
return tmp.Execute(f, table)
}) })
if err != nil { if err != nil {
panic(err) panic(err)
} }
exec.Command("gofmt", "-l", "-w", *savePath+"/..").Run() exec.Command("gofmt", "-l", "-w", *savePath+"/..").Run()
}
func filename(tableName string) string {
return strings.ToLower(strings.Join(strings.Split(tableName, "_"), ""))
}
func filterIndex(index []*ddl.TableIndex) []*ddl.TableIndex {
idxs := make([]*ddl.TableIndex, 0)
for _, v := range index {
if v.IsUnique {
idxs = append(idxs, v)
}
}
return idxs
}
func saveFile(fileName string, templateContent string, table *ddl.Table, isOnce bool) error {
if isOnce {
if pathx.Exists(fileName) {
return nil
}
}
f, err := os.Create(fileName)
if err != nil {
return err
}
defer f.Close()
return core.SaveFile(f, templateContent, table)
} }

@ -5,14 +5,27 @@ import (
"{{$val}}"{{end}} "{{$val}}"{{end}}
) )
{{end}} {{end}}
type {{.Name|UpperType}} struct { type (
{{.Name|LowerType}}Model interface {
Insert(ctx context.Context, data *{{.Name|UpperType}}) error
{{ if .Primary}}Update(ctx context.Context, {{.Primary.Name|LowerType}} {{.Primary.GoType}}, updates map[string]any) error
Delete(ctx context.Context, {{.Primary.Name|LowerType}} {{.Primary.GoType}}) error
FindOne(ctx context.Context, {{.Primary.Name|LowerType}} {{.Primary.GoType}}) (*{{.Name|UpperType}}, error){{end}}
{{range $val:= .Indexes}}Find{{$val.Name|UpperType}}(ctx context.Context {{range $column:=$val.Columns}},{{$column.Name|LowerType}} {{$column.GoType}}{{end}}) (*{{$.Name|UpperType}}, error){{end}}
}
{{.Name|UpperType}} struct {
updates map[string]any updates map[string]any
{{range $val := .Columns}}{{$val.Name|UpperType}} {{$val.GoType}} `db:"{{$val.Name}}"`{{if $val.Comment}}//{{$val.Comment}}{{end}} {{range $val := .Columns}}{{$val.Name|UpperType}} {{$val.GoType}} `db:"{{$val.Name}}"`{{if $val.Comment}}//{{$val.Comment}}{{end}}
{{end}} {{end}}
} }
default{{.Name|UpperType}}Model struct {
db *gorm.DB
}
)
func (s *{{.Name|UpperType}}) TableName() string { func (s *{{.Name|UpperType}}) TableName() string {
return "{{.Name}}" return "{{.Name}}"
} }
func New{{.Name|UpperType}}() *{{.Name|UpperType}} { func New{{.Name|UpperType}}() *{{.Name|UpperType}} {
return &{{.Name|UpperType}}{ return &{{.Name|UpperType}}{
updates: make(map[string]any), updates: make(map[string]any),
@ -26,7 +39,6 @@ func (s *{{$.Name|UpperType}}) Set{{$val.Name|UpperType}}({{$val.Name|LowerType}
s.set("{{$val.Name}}", {{$val.Name|LowerType}}) s.set("{{$val.Name}}", {{$val.Name|LowerType}})
} }
{{end}} {{end}}
func (s *{{.Name|UpperType}}) set(key string, val any) { func (s *{{.Name|UpperType}}) set(key string, val any) {
s.updates[key] = val s.updates[key] = val
} }
@ -37,41 +49,37 @@ func (s *{{.Name|UpperType}}) UpdateColumn() map[string]any {
type default{{.Name|UpperType}}DAO struct { func new{{.Name|UpperType}}DAO(db *gorm.DB) *default{{.Name|UpperType}}Model {
db *gorm.DB return &default{{.Name|UpperType}}Model{
}
func New{{.Name|UpperType}}DAO(db *gorm.DB) *default{{.Name|UpperType}}DAO {
return &default{{.Name|UpperType}}DAO{
db: db, db: db,
} }
} }
func (s *default{{.Name|UpperType}}DAO) Insert(ctx context.Context, data *{{.Name|UpperType}}) error { func (s *default{{.Name|UpperType}}Model) Insert(ctx context.Context, data *{{.Name|UpperType}}) error {
return s.db.Create(data).Error return s.db.Create(data).Error
} }
{{ if .Primary}} {{ if .Primary}}
func (s *default{{.Name|UpperType}}DAO) Update(ctx context.Context, {{.Primary.Name|LowerType}} {{.Primary.GoType}}, updates map[string]any) error { func (s *default{{.Name|UpperType}}Model) Update(ctx context.Context, {{.Primary.Name|LowerType}} {{.Primary.GoType}}, updates map[string]any) error {
return s.db.Model({{.Name|UpperType}}{}).Where("{{.Primary.Name}}=?", {{.Primary.Name|LowerType}}).Updates(updates).Error return s.db.Model({{.Name|UpperType}}{}).Where("{{.Primary.Name}}=?", {{.Primary.Name|LowerType}}).Updates(updates).Error
} }
func (s *default{{.Name|UpperType}}DAO) Delete(ctx context.Context, {{.Primary.Name|LowerType}} {{.Primary.GoType}}) error { func (s *default{{.Name|UpperType}}Model) Delete(ctx context.Context, {{.Primary.Name|LowerType}} {{.Primary.GoType}}) error {
return s.db.Where("{{.Primary.Name}}=?", {{.Primary.Name|LowerType}}).Delete(&{{.Name|UpperType}}{}).Error return s.db.Where("{{.Primary.Name}}=?", {{.Primary.Name|LowerType}}).Delete(&{{.Name|UpperType}}{}).Error
} }
func (s *default{{.Name|UpperType}}DAO) FindOne(ctx context.Context, {{.Primary.Name|LowerType}} {{.Primary.GoType}}) (*{{.Name|UpperType}}, error) { func (s *default{{.Name|UpperType}}Model) FindOne(ctx context.Context, {{.Primary.Name|LowerType}} {{.Primary.GoType}}) (*{{.Name|UpperType}}, error) {
row := {{.Name|UpperType}}{} row := {{.Name|UpperType}}{}
err := s.db.Where("{{.Primary.Name}}=?", {{.Primary.Name|LowerType}}).Find(&row).Error err := s.db.Where("{{.Primary.Name}}=?", {{.Primary.Name|LowerType}}).Find(&row).Error
if err!=nil{ return findResultWithError(&row,err)
return nil,err
}
return &row, nil
} }
{{end}} {{end}}
{{range $val:= .Indexes}} {{range $val:= .Indexes}}
func (s *default{{$.Name|UpperType}}DAO) Find{{$val.Name|UpperType}}(ctx context.Context {{range $column:=$val.Columns}},{{$column.Name|LowerType}} {{$column.GoType}}{{end}}) error { func (s *default{{$.Name|UpperType}}Model) Find{{$val.Name|UpperType}}(ctx context.Context {{range $column:=$val.Columns}},{{$column.Name|LowerType}} {{$column.GoType}}{{end}}) (*{{$.Name|UpperType}}, error) {
return s.db.Where("{{$val.Columns|UpdateColumn}}" {{range $column:=$val.Columns}},{{$column.Name|LowerType}}{{end}}).Delete(&{{$.Name|UpperType}}{}).Error row := {{$.Name|UpperType}}{}
err := s.db.Where("{{$val.Columns|UpdateColumn}}" {{range $column:=$val.Columns}},{{$column.Name|LowerType}}{{end}}).Find(&row).Error
return findResultWithError(&row,err)
} }
{{end}} {{end}}

@ -1,7 +0,0 @@
package errors
import (
"gorm.io/gorm"
)
var ErrNotFound = gorm.ErrRecordNotFound

@ -0,0 +1,47 @@
package builder
import (
"fmt"
"git.diulo.com/mogfee/kit/stringx"
"reflect"
"strings"
)
const dbTag = "db"
func RawFieldNames(in any) []string {
out := make([]string, 0)
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
panic(fmt.Errorf("ToMap only accepts structs; got %T", v))
}
typ := v.Type()
for i := 0; i < v.NumField(); i++ {
fi := typ.Field(i)
if !stringx.IsFirstUpper(fi.Name) {
continue
}
tagv := fi.Tag.Get(dbTag)
switch tagv {
case "-":
continue
case "":
out = append(out, fmt.Sprintf("`%s`", fi.Name))
default:
if strings.Contains(tagv, ",") {
tagv = strings.TrimSpace(strings.Split(tagv, ",")[0])
}
if tagv == "-" {
continue
}
if len(tagv) == 0 {
tagv = fi.Name
}
out = append(out, fmt.Sprintf("`%s`", tagv))
}
}
return out
}

@ -0,0 +1,23 @@
package builder
import (
"fmt"
"testing"
"time"
)
type AdminUser struct {
updates map[string]any
Id int64 `db:"id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
Status int32 `db:"status"`
Username string `db:"username"`
Password string `db:"password"`
RoleId int64 `db:"role_id"`
AliasId int32 `db:"alias_id"`
}
func TestBuild(t *testing.T) {
fmt.Println(RawFieldNames(AdminUser{}))
}

@ -0,0 +1,13 @@
package pathx
import (
"os"
)
func Exists(file string) bool {
_, err := os.Stat(file)
if os.IsNotExist(err) {
return false
}
return true
}

@ -0,0 +1,11 @@
package pathx
import (
"fmt"
"testing"
)
func TestExists(t *testing.T) {
fmt.Println(Exists("./a.txt"))
fmt.Println(Exists("./a1.txt"))
}

@ -1,6 +1,9 @@
package stringx package stringx
import "unicode" import (
"strings"
"unicode"
)
func Ucfirst(str string) string { func Ucfirst(str string) string {
for i, v := range str { for i, v := range str {
@ -15,3 +18,12 @@ func Lcfirst(str string) string {
} }
return "" return ""
} }
func IsFirstUpper(name string) bool {
for a, b := range name {
if a == 0 && string(b) == strings.ToUpper(string(b)) {
return true
}
break
}
return false
}

@ -0,0 +1,11 @@
package stringx
import (
"fmt"
"testing"
)
func TestIsFirstUpper(t *testing.T) {
fmt.Println(IsFirstUpper("abc"))
fmt.Println(IsFirstUpper("Abc"))
}

@ -0,0 +1,22 @@
package main
import (
"fmt"
"github.com/spf13/cobra"
)
func main() {
Cmd := &cobra.Command{
Use: "model",
}
mysqlCmd := &cobra.Command{
Use: "mysql",
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Println("aaa")
return nil
},
}
Cmd.AddCommand(mysqlCmd)
Cmd.Execute()
}

@ -0,0 +1,11 @@
package main
import "git.diulo.com/mogfee/kit/tools/model/sql/gen"
func main() {
filenmae := "/Users/mogfee/web/sendmail_server_new/sendmail.sch.sql"
err := gen.NewGenerator().StartFromDDL(filenmae, false, true, "sendmail")
if err != nil {
panic(err)
}
}

@ -0,0 +1,52 @@
package gen
import "git.diulo.com/mogfee/kit/mysql/ddl"
type (
defaultGenerator struct {
dir string
pkg string
ignoreColumns []string
}
code struct {
importsCode string
varsCode string
typesCode string
newCode string
insertCode string
findCode string
updateCode string
deleteCode string
cacheExtra string
tableName string
}
codeTuple struct {
modelCode string
modelCustomCode string
}
)
func NewGenerator() *defaultGenerator {
return &defaultGenerator{}
}
func (g *defaultGenerator) StartFromDDL(filename string, withCache, strict bool, database string) error {
modelList, err := g.genFromDDL(filename, withCache, strict, database)
if err != nil {
return err
}
return g.createFile(modelList)
}
func (g *defaultGenerator) genFromDDL(filename string, cache bool, strict bool, database string) (
map[string]*codeTuple, error) {
m := make(map[string]*codeTuple)
err := ddl.Parser(filename, func(table *ddl.Table) error {
code, err := g.genModel(e, cache)
if err != nil {
return err
}
})
return m, err
}

@ -0,0 +1,71 @@
package parser
import (
"git.diulo.com/mogfee/kit/mysql/ddl"
)
const timeImport = "time.Time"
type (
Table struct {
Name string
Db string
PrimaryKey Primary
UniqueIndex map[string][]*Field
Fields []*Field
}
Primary struct {
Field
AutoIncrement bool
}
Field struct {
NameOriginal string
Name string
DateType string
Comment string
SeqInIndex int
OrdinalPosition int
ContainsPQ bool
}
KeyType int
)
func parseNameOriginal(ts []*ddl.Table) (nameOriginals [][]string) {
var columns []string
for _, t := range ts {
columns = []string{}
for _, c := range t.Columns {
columns = append(columns, c.Name)
}
nameOriginals = append(nameOriginals, columns)
}
return nameOriginals
}
func Parse(filename, database string, strict bool) ([]*Table, error) {
list := make([]*Table, 0)
err := ddl.Parser(filename, func(table *ddl.Table) error {
list = append(list, &Table{
Name: table.Name,
Db: "",
PrimaryKey: Primary{
Field: Field{
NameOriginal: "",
Name: "",
DateType: "",
Comment: "",
SeqInIndex: 0,
OrdinalPosition: 0,
ContainsPQ: false,
},
AutoIncrement: false,
},
UniqueIndex: nil,
Fields: nil,
})
return nil
})
return list, err
}
Loading…
Cancel
Save