Skip to content
This repository was archived by the owner on Jun 17, 2025. It is now read-only.

Commit 912abf0

Browse files
committed
feat: add gen.go
1 parent 06a2cf1 commit 912abf0

File tree

6 files changed

+219
-2
lines changed

6 files changed

+219
-2
lines changed

cmd/static/model_flags.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,15 @@ func modelFlags() []cli.Flag {
5151
&cli.BoolFlag{Name: consts.TypeTag, Usage: "Specify generate field with gorm column type tag", Value: false, DefaultText: "false"},
5252
&cli.BoolFlag{Name: consts.IndexTag, Usage: "Specify generate field with gorm index tag", Value: false, DefaultText: "false"},
5353
&cli.StringFlag{Name: consts.SQLDir, Usage: "Specify a sql file or directory", Value: "", DefaultText: ""},
54+
&cli.StringFlag{Name: consts.Mode, Usage: modeUsage, Value: "noctx,defaultquery,queryinterface", DefaultText: "noctx,defaultquery,queryinterface"},
5455
}
5556
}
57+
58+
const modeUsage = `Specify gorm/gen generator mode
59+
(https://gorm.io/gen/dao.html#Generator-Modes).
60+
There is no need to follow strict case, we offer some abbreviations
61+
62+
- WithoutContext (noctx)
63+
- WithDefaultQuery (defaultquery)
64+
- WithQueryInterface (queryinterface)
65+
`

config/model.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type ModelArgument struct {
3838
FieldWithIndexTag bool
3939
FieldWithTypeTag bool
4040
SQLDir string
41+
Mode string
4142
}
4243

4344
func NewModelArgument() *ModelArgument {
@@ -62,5 +63,6 @@ func (c *ModelArgument) ParseCli(ctx *cli.Context) error {
6263
c.FieldWithIndexTag = ctx.Bool(consts.IndexTag)
6364
c.FieldWithTypeTag = ctx.Bool(consts.TypeTag)
6465
c.SQLDir = ctx.String(consts.SQLDir)
66+
c.Mode = ctx.String(consts.Mode)
6567
return nil
6668
}

pkg/consts/const.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ const (
159159
TypeTag = "type_tag"
160160
HexTag = "hex"
161161
SQLDir = "sql_dir"
162+
Mode = "mode"
162163
)
163164

164165
const (

pkg/model/generator_tpl.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package model
2+
3+
import (
4+
"bytes"
5+
_ "embed"
6+
"fmt"
7+
"go/format"
8+
"path/filepath"
9+
"text/template"
10+
11+
"github.com/cloudwego/cwgo/config"
12+
"github.com/cloudwego/cwgo/pkg/consts"
13+
14+
"gorm.io/gen"
15+
)
16+
17+
//go:embed model_tpl.txt
18+
var mergedTemplate string
19+
20+
type GenMethodTmpl struct {
21+
GormOpen string
22+
gen.Config
23+
OnlyModel bool
24+
// UseRawSQL indicates whether to use raw SQL for the database connection
25+
UseRawSQL bool
26+
Tables []string
27+
StrategyParams struct {
28+
ExcludeTables []string
29+
Type string
30+
}
31+
}
32+
33+
func execTmpl(c *config.ModelArgument) ([]byte, error) {
34+
tpl, err := template.New("merged").Parse(mergedTemplate)
35+
if err != nil {
36+
return nil, fmt.Errorf("parse template fail: %w", err)
37+
}
38+
39+
absOutPath, _ := filepath.Abs(c.OutPath)
40+
data := GenMethodTmpl{
41+
GormOpen: buildGormOpen(c),
42+
UseRawSQL: c.DSN == "" && c.SQLDir != "",
43+
Tables: c.Tables,
44+
OnlyModel: c.OnlyModel,
45+
Config: gen.Config{
46+
OutPath: absOutPath,
47+
OutFile: c.OutFile,
48+
ModelPkgPath: c.ModelPkgName,
49+
WithUnitTest: c.WithUnitTest,
50+
FieldNullable: c.FieldNullable,
51+
FieldSignable: c.FieldSignable,
52+
FieldWithIndexTag: c.FieldWithIndexTag,
53+
FieldWithTypeTag: c.FieldWithTypeTag,
54+
Mode: buildGenMode(c.Mode),
55+
},
56+
StrategyParams: struct {
57+
ExcludeTables []string
58+
Type string
59+
}{
60+
ExcludeTables: c.ExcludeTables,
61+
Type: c.Type,
62+
},
63+
}
64+
65+
var buf bytes.Buffer
66+
err = tpl.Execute(&buf, data)
67+
if err != nil {
68+
return nil, fmt.Errorf("execute template fail: %w", err)
69+
}
70+
fmtCode, err := format.Source(buf.Bytes())
71+
return fmtCode, err
72+
}
73+
74+
func buildGormOpen(c *config.ModelArgument) string {
75+
abs, _ := filepath.Abs(c.SQLDir)
76+
switch {
77+
case c.SQLDir != "":
78+
return fmt.Sprintf(
79+
"db, err := gorm.Open(rawsql.New(rawsql.Config{FilePath: []string{%q}}))",
80+
abs,
81+
)
82+
case c.DSN != "" && c.Type != "":
83+
return fmt.Sprintf(
84+
"db, err := gorm.Open(%s.Open(%q))",
85+
consts.DataBaseType(c.Type),
86+
c.DSN,
87+
)
88+
default:
89+
return ""
90+
}
91+
}

pkg/model/model.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ package model
1818

1919
import (
2020
"fmt"
21+
"os"
22+
"path/filepath"
23+
"regexp"
2124
"strings"
2225

2326
"gorm.io/rawsql"
@@ -57,6 +60,7 @@ func Model(c *config.ModelArgument) error {
5760
FieldSignable: c.FieldSignable,
5861
FieldWithIndexTag: c.FieldWithIndexTag,
5962
FieldWithTypeTag: c.FieldWithTypeTag,
63+
Mode: buildGenMode(c.Mode),
6064
}
6165

6266
if len(c.ExcludeTables) > 0 || c.Type == string(consts.Sqlite) {
@@ -87,9 +91,12 @@ func Model(c *config.ModelArgument) error {
8791
if !c.OnlyModel {
8892
g.ApplyBasic(models...)
8993
}
90-
9194
g.Execute()
92-
return nil
95+
getwd, _ := os.Getwd()
96+
outPath := filepath.Join(getwd, c.OutPath)
97+
genMainFileRootDir := filepath.Dir(outPath)
98+
buf, err := execTmpl(c)
99+
return os.WriteFile(filepath.Join(genMainFileRootDir, "gen.go"), buf, 0o644)
93100
}
94101

95102
func genModels(g *gen.Generator, db *gorm.DB, tables []string) (models []interface{}, err error) {
@@ -109,3 +116,21 @@ func genModels(g *gen.Generator, db *gorm.DB, tables []string) (models []interfa
109116
}
110117
return models, nil
111118
}
119+
120+
func buildGenMode(mode string) gen.GenerateMode {
121+
var generateMode gen.GenerateMode
122+
ss := regexp.MustCompile(`[,;\s]+`).Split(strings.ToLower(mode), -1)
123+
for _, s := range ss {
124+
s = strings.TrimSpace(s)
125+
switch s {
126+
case "withoutcontext", "noctx":
127+
generateMode |= gen.WithoutContext
128+
case "withdefaultquery", "defaultquery":
129+
generateMode |= gen.WithDefaultQuery
130+
case "withqueryinterface", "queryinterface":
131+
generateMode |= gen.WithQueryInterface
132+
default:
133+
}
134+
}
135+
return generateMode
136+
}

pkg/model/model_tpl.txt

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
{{ define "GORM_OPEN" }}
2+
{{ .GormOpen }}
3+
if err != nil {
4+
log.Fatal("open db fail: ", err)
5+
}
6+
{{ end }}
7+
8+
{{ define "GEN_CONFIG" }}
9+
genConfig := gen.Config{
10+
OutPath: {{ printf "%q" .OutPath }},
11+
OutFile: {{ printf "%q" .OutFile }},
12+
ModelPkgPath: {{ printf "%q" .ModelPkgPath }},
13+
WithUnitTest: {{ .WithUnitTest }},
14+
FieldNullable: {{ .FieldNullable }},
15+
FieldSignable: {{ .FieldSignable }},
16+
FieldWithIndexTag: {{ .FieldWithIndexTag }},
17+
FieldWithTypeTag: {{ .FieldWithTypeTag }},
18+
Mode: {{ .Mode }},
19+
}
20+
{{ end }}
21+
22+
{{ define "TABLE_STRATEGY" }}
23+
{{if or (gt (len .ExcludeTables) 0) (eq .Type "sqlite") }}
24+
genConfig.WithTableNameStrategy(func(tableName string) string {
25+
{{if eq .Type "sqlite" -}}
26+
if strings.HasPrefix(tableName, "sqlite") {
27+
return ""
28+
}
29+
{{end -}}
30+
{{if gt (len .ExcludeTables) 0 -}}
31+
switch tableName {
32+
{{range $table := .ExcludeTables -}}
33+
case "{{ $table }}":
34+
return ""
35+
{{end -}}
36+
}
37+
{{end -}}
38+
return tableName
39+
})
40+
{{end}}
41+
{{ end }}
42+
43+
package main
44+
45+
import (
46+
"fmt"
47+
"log"
48+
49+
"gorm.io/gorm"
50+
"gorm.io/gen"
51+
{{if .UseRawSQL }} "gorm.io/rawsql" {{end}}
52+
)
53+
54+
func main() {
55+
{{ template "GORM_OPEN" . }}
56+
{{ template "GEN_CONFIG" .Config }}
57+
{{ template "TABLE_STRATEGY" .StrategyParams }}
58+
59+
g := gen.NewGenerator(genConfig)
60+
g.UseDB(db)
61+
models, err := genModels(g, db, []string{ {{- range $index, $element := .Tables }}
62+
{{- if $index }}, {{ end }}"{{$element}}"{{- end }} })
63+
if err != nil {
64+
log.Fatal("gen models fail: ", err)
65+
}
66+
{{if not .OnlyModel}}
67+
g.ApplyBasic(models...)
68+
{{end}}
69+
g.Execute()
70+
}
71+
72+
func genModels(g *gen.Generator, db *gorm.DB, tables []string) (models []interface{}, err error) {
73+
var tablesNameList []string
74+
if len(tables) == 0 {
75+
tablesNameList, err = db.Migrator().GetTables()
76+
if err != nil {
77+
return nil, fmt.Errorf("migrator get all tables fail: %w", err)
78+
}
79+
} else {
80+
tablesNameList = tables
81+
}
82+
83+
models = make([]interface{}, len(tablesNameList))
84+
for i, tableName := range tablesNameList {
85+
models[i] = g.GenerateModel(tableName)
86+
}
87+
return models, nil
88+
}

0 commit comments

Comments
 (0)