gocctl model v20200819 (#18)
* rename snake、came method * new: generate model from data source * add change log md * update model doc * update doc * beauty code
This commit is contained in:
@@ -195,6 +195,13 @@ ts需要指定webapi所在目录
|
||||
goctl api dart -api user/user.api -dir ./src
|
||||
```
|
||||
|
||||
## 根据mysql ddl或者datasource生成model文件
|
||||
|
||||
```shell script
|
||||
$ goctl model mysql -src={filename} -dir={dir} -cache={true|false}
|
||||
```
|
||||
详情参考[model文档](https://github.com/tal-tech/go-zero/blob/master/tools/goctl/model/sql/README.MD)
|
||||
|
||||
## 根据定义好的简单go文件生成mongo代码文件(仅限golang使用)
|
||||
```shell
|
||||
goctl model mongo -src {{yourDir}}/xiao/service/xhb/user/model/usermodel.go -cache yes
|
||||
@@ -218,7 +225,7 @@ type User struct {
|
||||
o是改字段需要生产的操作函数 可以取得get,find,set 分别表示生成返回单个对象的查询方法,返回多个对象的查询方法,设置该字段方法
|
||||
生成的目标文件会覆盖该简单go文件
|
||||
|
||||
## goctl rpc生成
|
||||
## goctl rpc生成(业务剥离中,暂未开放)
|
||||
|
||||
命令 `goctl rpc proto -proto ${proto} -service ${serviceName} -project ${projectName} -dir ${directory} -shared ${shared}`
|
||||
如: `goctl rpc proto -proto test.proto -service test -project xjy -dir .`
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/tal-tech/go-zero/core/logx"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/api/apigen"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/api/dartgen"
|
||||
@@ -18,7 +20,6 @@ import (
|
||||
"github.com/tal-tech/go-zero/tools/goctl/docker"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/feature"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/command"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -191,25 +192,64 @@ var (
|
||||
{
|
||||
Name: "model",
|
||||
Usage: "generate model code",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "src, s",
|
||||
Usage: "the file path of the ddl source file",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "dir, d",
|
||||
Usage: "the target dir",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "cache, c",
|
||||
Usage: "generate code with cache [optional]",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "idea",
|
||||
Usage: "for idea plugin [optional]",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "mysql",
|
||||
Usage: `generate mysql model"`,
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "ddl",
|
||||
Usage: `generate mysql model from ddl"`,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "src, s",
|
||||
Usage: "the file path of the ddl source file",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "dir, d",
|
||||
Usage: "the target dir",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "cache, c",
|
||||
Usage: "generate code with cache [optional]",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "idea",
|
||||
Usage: "for idea plugin [optional]",
|
||||
},
|
||||
},
|
||||
Action: command.MysqlDDL,
|
||||
},
|
||||
{
|
||||
Name: "datasource",
|
||||
Usage: `generate model from datasource"`,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "url",
|
||||
Usage: `the data source of database,like "root:password@tcp(127.0.0.1:3306)/database"`,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "table, t",
|
||||
Usage: `source table,tables separated by commas,like "user,course"`,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "cache, c",
|
||||
Usage: "generate code with cache [optional]",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "dir, d",
|
||||
Usage: "the target dir",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "idea",
|
||||
Usage: "for idea plugin [optional]",
|
||||
},
|
||||
},
|
||||
Action: command.MyDataSource,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: command.Mysql,
|
||||
},
|
||||
{
|
||||
Name: "config",
|
||||
|
||||
10
tools/goctl/model/sql/CHANGELOG.md
Normal file
10
tools/goctl/model/sql/CHANGELOG.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Change log
|
||||
|
||||
# 2020-08-20
|
||||
* 新增支持通过连接数据库生成model
|
||||
* 支持数据库多表生成
|
||||
* 优化stringx
|
||||
|
||||
# 2020-08-19
|
||||
* 重构model代码生成逻辑
|
||||
* 实现从ddl解析表信息生成代码
|
||||
@@ -4,21 +4,28 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
||||
|
||||
# 快速开始
|
||||
|
||||
```
|
||||
$ goctl model -src ./sql/user.sql -dir ./model -c true
|
||||
```
|
||||
* 通过ddl生成
|
||||
|
||||
详情用法请参考[example](https://github.com/tal-tech/go-zero/tools/goctl/model/sql/example)
|
||||
```shell script
|
||||
$ goctl model mysql ddl -src="./sql/user.sql" -dir="./sql/model" -c=true
|
||||
```
|
||||
|
||||
执行上述命令后即可快速生成CURD代码。
|
||||
执行上述命令后即可快速生成CURD代码。
|
||||
|
||||
```
|
||||
model
|
||||
│ ├── error.go
|
||||
│ └── usermodel.go
|
||||
```
|
||||
```
|
||||
model
|
||||
│ ├── error.go
|
||||
│ └── usermodel.go
|
||||
```
|
||||
* 通过datasource生成
|
||||
|
||||
```shell script
|
||||
$ goctl model mysql datasource -url="user:password@tcp(127.0.0.1:3306)/database" -table="table1,table2" -dir="./model"
|
||||
```
|
||||
|
||||
|
||||
> 详情用法请参考[example](https://github.com/tal-tech/go-zero/tree/master/tools/goctl/model/sql/example)
|
||||
|
||||
> 注意:这里的目录结构中有usercoursemodel.go目录,在example中我为了体现带cache与不带cache代码的区别,因此将sql文件分别使用了独立的sql文件(user.sql&course.sql),在实际项目开发中你可以将ddl建表语句放在一个sql文件中,`goctl model`会自动解析并分割,最终按照每个ddl建表语句为单位生成独立的go文件。
|
||||
|
||||
* 生成代码示例
|
||||
|
||||
@@ -174,22 +181,22 @@ model
|
||||
# 用法
|
||||
|
||||
```
|
||||
$ goctl model -h
|
||||
$ goctl model mysql -h
|
||||
```
|
||||
|
||||
```
|
||||
NAME:
|
||||
goctl model - generate model code
|
||||
goctl model mysql - generate mysql model"
|
||||
|
||||
USAGE:
|
||||
goctl model [command options] [arguments...]
|
||||
goctl model mysql command [command options] [arguments...]
|
||||
|
||||
COMMANDS:
|
||||
ddl generate mysql model from ddl"
|
||||
datasource generate model from datasource"
|
||||
|
||||
OPTIONS:
|
||||
--src value, -s value the file path of the ddl source file
|
||||
--dir value, -d value the target dir
|
||||
--cache, -c generate code with cache [optional]
|
||||
--idea for idea plugin [optional]
|
||||
|
||||
--help, -h show help
|
||||
```
|
||||
|
||||
# 生成规则
|
||||
@@ -198,22 +205,43 @@ OPTIONS:
|
||||
|
||||
我们默认用户在建表时会创建createTime、updateTime字段(忽略大小写、下划线命名风格)且默认值均为`CURRENT_TIMESTAMP`,而updateTime支持`ON UPDATE CURRENT_TIMESTAMP`,对于这两个字段生成`insert`、`update`时会被移除,不在赋值范畴内,当然,如果你不需要这两个字段那也无大碍。
|
||||
* 带缓存模式
|
||||
|
||||
```
|
||||
$ goctl model -src {filename} -dir {dir} -cache true
|
||||
```
|
||||
* ddl
|
||||
|
||||
```shell script
|
||||
$ goctl model mysql -src={filename} -dir={dir} -cache=true
|
||||
```
|
||||
* datasource
|
||||
|
||||
```shell script
|
||||
$ goctl model mysql datasource -url={datasource} -table={tables} -dir={dir} -cache=true
|
||||
```
|
||||
|
||||
目前仅支持redis缓存,如果选择带缓存模式,即生成的`FindOne(ByXxx)`&`Delete`代码会生成带缓存逻辑的代码,目前仅支持单索引字段(除全文索引外),对于联合索引我们默认认为不需要带缓存,且不属于通用型代码,因此没有放在代码生成行列,如example中user表中的`id`、`name`、`mobile`字段均属于单字段索引。
|
||||
|
||||
* 不带缓存模式
|
||||
|
||||
```
|
||||
$ goctl model -src {filename} -dir {dir}
|
||||
```
|
||||
* ddl
|
||||
|
||||
```shell script
|
||||
$ goctl model -src={filename} -dir={dir}
|
||||
```
|
||||
* datasource
|
||||
|
||||
```shell script
|
||||
$ goctl model mysql datasource -url={datasource} -table={tables} -dir={dir}
|
||||
```
|
||||
or
|
||||
```
|
||||
$ goctl model -src {filename} -dir {dir} -cache false
|
||||
```
|
||||
* ddl
|
||||
|
||||
```shell script
|
||||
$ goctl model -src={filename} -dir={dir} -cache=false
|
||||
```
|
||||
* datasource
|
||||
|
||||
```shell script
|
||||
$ goctl model mysql datasource -url={datasource} -table={tables} -dir={dir} -cache=false
|
||||
```
|
||||
|
||||
生成代码仅基本的CURD结构。
|
||||
|
||||
# 缓存
|
||||
@@ -238,10 +266,6 @@ OPTIONS:
|
||||
|
||||
# QA
|
||||
|
||||
* goctl model支持根据数据库连接后选择表生成代码吗?
|
||||
|
||||
目前暂时不支持,在后面会向这个方向扩展。
|
||||
|
||||
* goctl model除了命令行模式,支持插件模式吗?
|
||||
|
||||
很快支持idea插件。
|
||||
|
||||
@@ -1,24 +1,85 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/gen"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util/console"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/tal-tech/go-zero/core/collection"
|
||||
"github.com/tal-tech/go-zero/core/logx"
|
||||
"github.com/tal-tech/go-zero/core/stores/sqlx"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/gen"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util/console"
|
||||
)
|
||||
|
||||
func Mysql(ctx *cli.Context) error {
|
||||
src := ctx.String("src")
|
||||
dir := ctx.String("dir")
|
||||
cache := ctx.Bool("cache")
|
||||
idea := ctx.Bool("idea")
|
||||
var log console.Console
|
||||
if idea {
|
||||
log = console.NewIdeaConsole()
|
||||
} else {
|
||||
log = console.NewColorConsole()
|
||||
const (
|
||||
flagSrc = "src"
|
||||
flagDir = "dir"
|
||||
flagCache = "cache"
|
||||
flagIdea = "idea"
|
||||
flagUrl = "url"
|
||||
flagTable = "table"
|
||||
)
|
||||
|
||||
func MysqlDDL(ctx *cli.Context) error {
|
||||
src := ctx.String(flagSrc)
|
||||
dir := ctx.String(flagDir)
|
||||
cache := ctx.Bool(flagCache)
|
||||
idea := ctx.Bool(flagIdea)
|
||||
log := console.NewConsole(idea)
|
||||
fileSrc, err := filepath.Abs(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
generator := gen.NewDefaultGenerator(src, dir, gen.WithConsoleOption(log))
|
||||
err := generator.Start(cache)
|
||||
data, err := ioutil.ReadFile(fileSrc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
source := string(data)
|
||||
generator := gen.NewDefaultGenerator(source, dir, gen.WithConsoleOption(log))
|
||||
err = generator.Start(cache)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func MyDataSource(ctx *cli.Context) error {
|
||||
url := strings.TrimSpace(ctx.String(flagUrl))
|
||||
dir := strings.TrimSpace(ctx.String(flagDir))
|
||||
cache := ctx.Bool(flagCache)
|
||||
idea := ctx.Bool(flagIdea)
|
||||
table := strings.TrimSpace(ctx.String(flagTable))
|
||||
log := console.NewConsole(idea)
|
||||
if len(url) == 0 {
|
||||
log.Error("%v", "expected data source of mysql, but is empty")
|
||||
return nil
|
||||
}
|
||||
if len(table) == 0 {
|
||||
log.Error("%v", "expected table(s), but nothing found")
|
||||
return nil
|
||||
}
|
||||
logx.Disable()
|
||||
conn := sqlx.NewMysql(url)
|
||||
m := model.NewDDLModel(conn)
|
||||
tables := collection.NewSet()
|
||||
for _, item := range strings.Split(table, ",") {
|
||||
item = strings.TrimSpace(item)
|
||||
if len(item) == 0 {
|
||||
continue
|
||||
}
|
||||
tables.AddStr(item)
|
||||
}
|
||||
ddl, err := m.ShowDDL(tables.KeysStr()...)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
return nil
|
||||
}
|
||||
generator := gen.NewDefaultGenerator(strings.Join(ddl, "\n"), dir, gen.WithConsoleOption(log))
|
||||
err = generator.Start(cache)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# generate usermodel with cache
|
||||
goctl model -src ./sql/user.sql -dir ./model -c true
|
||||
# generate model with cache from ddl
|
||||
goctl model mysql ddl -src="./sql/user.sql" -dir="./sql/model" -c=true
|
||||
|
||||
# generate model with cache from data source
|
||||
goctl model mysql datasource -url="user:password@tcp(127.0.0.1:3306)/database" -table="table1,table2" -dir="./model"
|
||||
@@ -27,14 +27,14 @@ func genDelete(table Table, withCache bool) (string, error) {
|
||||
break
|
||||
}
|
||||
}
|
||||
camel := table.Name.Snake2Camel()
|
||||
camel := table.Name.ToCamel()
|
||||
output, err := templatex.With("delete").
|
||||
Parse(template.Delete).
|
||||
Execute(map[string]interface{}{
|
||||
"upperStartCamelObject": camel,
|
||||
"withCache": withCache,
|
||||
"containsIndexCache": containsIndexCache,
|
||||
"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.Snake2Camel()).LowerStart(),
|
||||
"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.ToCamel()).UnTitle(),
|
||||
"dataType": table.PrimaryKey.DataType,
|
||||
"keys": strings.Join(keySet.KeysStr(), "\n"),
|
||||
"originalPrimaryKey": table.PrimaryKey.Name.Source(),
|
||||
|
||||
@@ -28,7 +28,7 @@ func genField(field parser.Field) (string, error) {
|
||||
output, err := templatex.With("types").
|
||||
Parse(template.Field).
|
||||
Execute(map[string]interface{}{
|
||||
"name": field.Name.Snake2Camel(),
|
||||
"name": field.Name.ToCamel(),
|
||||
"type": field.DataType,
|
||||
"tag": tag,
|
||||
"hasComment": field.Comment != "",
|
||||
|
||||
@@ -7,15 +7,15 @@ import (
|
||||
)
|
||||
|
||||
func genFindOne(table Table, withCache bool) (string, error) {
|
||||
camel := table.Name.Snake2Camel()
|
||||
camel := table.Name.ToCamel()
|
||||
output, err := templatex.With("findOne").
|
||||
Parse(template.FindOne).
|
||||
Execute(map[string]interface{}{
|
||||
"withCache": withCache,
|
||||
"upperStartCamelObject": camel,
|
||||
"lowerStartCamelObject": stringx.From(camel).LowerStart(),
|
||||
"lowerStartCamelObject": stringx.From(camel).UnTitle(),
|
||||
"originalPrimaryKey": table.PrimaryKey.Name.Source(),
|
||||
"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.Snake2Camel()).LowerStart(),
|
||||
"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.ToCamel()).UnTitle(),
|
||||
"dataType": table.PrimaryKey.DataType,
|
||||
"cacheKey": table.CacheKey[table.PrimaryKey.Name.Source()].KeyExpression,
|
||||
"cacheKeyVariable": table.CacheKey[table.PrimaryKey.Name.Source()].Variable,
|
||||
|
||||
@@ -12,23 +12,23 @@ import (
|
||||
func genFineOneByField(table Table, withCache bool) (string, error) {
|
||||
t := templatex.With("findOneByField").Parse(template.FindOneByField)
|
||||
var list []string
|
||||
camelTableName := table.Name.Snake2Camel()
|
||||
camelTableName := table.Name.ToCamel()
|
||||
for _, field := range table.Fields {
|
||||
if field.IsPrimaryKey || !field.IsKey {
|
||||
continue
|
||||
}
|
||||
camelFieldName := field.Name.Snake2Camel()
|
||||
camelFieldName := field.Name.ToCamel()
|
||||
output, err := t.Execute(map[string]interface{}{
|
||||
"upperStartCamelObject": camelTableName,
|
||||
"upperField": camelFieldName,
|
||||
"in": fmt.Sprintf("%s %s", stringx.From(camelFieldName).LowerStart(), field.DataType),
|
||||
"in": fmt.Sprintf("%s %s", stringx.From(camelFieldName).UnTitle(), field.DataType),
|
||||
"withCache": withCache,
|
||||
"cacheKey": table.CacheKey[field.Name.Source()].KeyExpression,
|
||||
"cacheKeyVariable": table.CacheKey[field.Name.Source()].Variable,
|
||||
"primaryKeyLeft": table.CacheKey[table.PrimaryKey.Name.Source()].Left,
|
||||
"lowerStartCamelObject": stringx.From(camelTableName).LowerStart(),
|
||||
"lowerStartCamelField": stringx.From(camelFieldName).LowerStart(),
|
||||
"upperStartCamelPrimaryKey": table.PrimaryKey.Name.Snake2Camel(),
|
||||
"lowerStartCamelObject": stringx.From(camelTableName).UnTitle(),
|
||||
"lowerStartCamelField": stringx.From(camelFieldName).UnTitle(),
|
||||
"upperStartCamelPrimaryKey": table.PrimaryKey.Name.ToCamel(),
|
||||
"originalField": field.Name.Source(),
|
||||
"originalPrimaryField": table.PrimaryKey.Name.Source(),
|
||||
})
|
||||
|
||||
@@ -23,21 +23,17 @@ const (
|
||||
type (
|
||||
defaultGenerator struct {
|
||||
source string
|
||||
src string
|
||||
dir string
|
||||
console.Console
|
||||
}
|
||||
Option func(generator *defaultGenerator)
|
||||
)
|
||||
|
||||
func NewDefaultGenerator(src, dir string, opt ...Option) *defaultGenerator {
|
||||
if src == "" {
|
||||
src = pwd
|
||||
}
|
||||
func NewDefaultGenerator(source, dir string, opt ...Option) *defaultGenerator {
|
||||
if dir == "" {
|
||||
dir = pwd
|
||||
}
|
||||
generator := &defaultGenerator{src: src, dir: dir}
|
||||
generator := &defaultGenerator{source: source, dir: dir}
|
||||
var optionList []Option
|
||||
optionList = append(optionList, newDefaultOption())
|
||||
optionList = append(optionList, opt...)
|
||||
@@ -60,10 +56,6 @@ func newDefaultOption() Option {
|
||||
}
|
||||
|
||||
func (g *defaultGenerator) Start(withCache bool) error {
|
||||
fileSrc, err := filepath.Abs(g.src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dirAbs, err := filepath.Abs(g.dir)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -72,21 +64,16 @@ func (g *defaultGenerator) Start(withCache bool) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := ioutil.ReadFile(fileSrc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.source = string(data)
|
||||
modelList, err := g.genFromDDL(withCache)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for tableName, code := range modelList {
|
||||
name := fmt.Sprintf("%smodel.go", strings.ToLower(stringx.From(tableName).Snake2Camel()))
|
||||
name := fmt.Sprintf("%smodel.go", strings.ToLower(stringx.From(tableName).ToCamel()))
|
||||
filename := filepath.Join(dirAbs, name)
|
||||
if util.FileExists(filename) {
|
||||
g.Warning("%s already exists,ignored.", name)
|
||||
g.Warning("%s already exists, ignored.", name)
|
||||
continue
|
||||
}
|
||||
err = ioutil.WriteFile(filename, []byte(code), os.ModePerm)
|
||||
|
||||
@@ -12,7 +12,7 @@ func genInsert(table Table, withCache bool) (string, error) {
|
||||
expressions := make([]string, 0)
|
||||
expressionValues := make([]string, 0)
|
||||
for _, filed := range table.Fields {
|
||||
camel := filed.Name.Snake2Camel()
|
||||
camel := filed.Name.ToCamel()
|
||||
if camel == "CreateTime" || camel == "UpdateTime" {
|
||||
continue
|
||||
}
|
||||
@@ -22,13 +22,13 @@ func genInsert(table Table, withCache bool) (string, error) {
|
||||
expressions = append(expressions, "?")
|
||||
expressionValues = append(expressionValues, "data."+camel)
|
||||
}
|
||||
camel := table.Name.Snake2Camel()
|
||||
camel := table.Name.ToCamel()
|
||||
output, err := templatex.With("insert").
|
||||
Parse(template.Insert).
|
||||
Execute(map[string]interface{}{
|
||||
"withCache": withCache,
|
||||
"upperStartCamelObject": camel,
|
||||
"lowerStartCamelObject": stringx.From(camel).LowerStart(),
|
||||
"lowerStartCamelObject": stringx.From(camel).UnTitle(),
|
||||
"expression": strings.Join(expressions, ", "),
|
||||
"expressionValues": strings.Join(expressionValues, ", "),
|
||||
})
|
||||
|
||||
@@ -26,14 +26,14 @@ type (
|
||||
func genCacheKeys(table parser.Table) (map[string]Key, error) {
|
||||
fields := table.Fields
|
||||
m := make(map[string]Key)
|
||||
camelTableName := table.Name.Snake2Camel()
|
||||
lowerStartCamelTableName := stringx.From(camelTableName).LowerStart()
|
||||
camelTableName := table.Name.ToCamel()
|
||||
lowerStartCamelTableName := stringx.From(camelTableName).UnTitle()
|
||||
for _, field := range fields {
|
||||
if !field.IsKey {
|
||||
continue
|
||||
}
|
||||
camelFieldName := field.Name.Snake2Camel()
|
||||
lowerStartCamelFieldName := stringx.From(camelFieldName).LowerStart()
|
||||
camelFieldName := field.Name.ToCamel()
|
||||
lowerStartCamelFieldName := stringx.From(camelFieldName).UnTitle()
|
||||
left := fmt.Sprintf("cache%s%sPrefix", camelTableName, camelFieldName)
|
||||
right := fmt.Sprintf("cache#%s#%s#", camelTableName, lowerStartCamelFieldName)
|
||||
variable := fmt.Sprintf("%s%sKey", lowerStartCamelTableName, camelFieldName)
|
||||
|
||||
@@ -10,7 +10,7 @@ func genNew(table Table, withCache bool) (string, error) {
|
||||
Parse(template.New).
|
||||
Execute(map[string]interface{}{
|
||||
"withCache": withCache,
|
||||
"upperStartCamelObject": table.Name.Snake2Camel(),
|
||||
"upperStartCamelObject": table.Name.ToCamel(),
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
@@ -15,7 +15,7 @@ func genTypes(table Table, withCache bool) (string, error) {
|
||||
Parse(template.Types).
|
||||
Execute(map[string]interface{}{
|
||||
"withCache": withCache,
|
||||
"upperStartCamelObject": table.Name.Snake2Camel(),
|
||||
"upperStartCamelObject": table.Name.ToCamel(),
|
||||
"fields": fieldsString,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
func genUpdate(table Table, withCache bool) (string, error) {
|
||||
expressionValues := make([]string, 0)
|
||||
for _, filed := range table.Fields {
|
||||
camel := filed.Name.Snake2Camel()
|
||||
camel := filed.Name.ToCamel()
|
||||
if camel == "CreateTime" || camel == "UpdateTime" {
|
||||
continue
|
||||
}
|
||||
@@ -20,8 +20,8 @@ func genUpdate(table Table, withCache bool) (string, error) {
|
||||
}
|
||||
expressionValues = append(expressionValues, "data."+camel)
|
||||
}
|
||||
expressionValues = append(expressionValues, "data."+table.PrimaryKey.Name.Snake2Camel())
|
||||
camelTableName := table.Name.Snake2Camel()
|
||||
expressionValues = append(expressionValues, "data."+table.PrimaryKey.Name.ToCamel())
|
||||
camelTableName := table.Name.ToCamel()
|
||||
output, err := templatex.With("update").
|
||||
Parse(template.Update).
|
||||
Execute(map[string]interface{}{
|
||||
@@ -29,7 +29,7 @@ func genUpdate(table Table, withCache bool) (string, error) {
|
||||
"upperStartCamelObject": camelTableName,
|
||||
"primaryCacheKey": table.CacheKey[table.PrimaryKey.Name.Source()].DataKeyExpression,
|
||||
"primaryKeyVariable": table.CacheKey[table.PrimaryKey.Name.Source()].Variable,
|
||||
"lowerStartCamelObject": stringx.From(camelTableName).LowerStart(),
|
||||
"lowerStartCamelObject": stringx.From(camelTableName).UnTitle(),
|
||||
"originalPrimaryKey": table.PrimaryKey.Name.Source(),
|
||||
"expressionValues": strings.Join(expressionValues, ", "),
|
||||
})
|
||||
|
||||
@@ -13,12 +13,12 @@ func genVars(table Table, withCache bool) (string, error) {
|
||||
for _, v := range table.CacheKey {
|
||||
keys = append(keys, v.VarExpression)
|
||||
}
|
||||
camel := table.Name.Snake2Camel()
|
||||
camel := table.Name.ToCamel()
|
||||
output, err := templatex.With("var").
|
||||
Parse(template.Vars).
|
||||
GoFmt(true).
|
||||
Execute(map[string]interface{}{
|
||||
"lowerStartCamelObject": stringx.From(camel).LowerStart(),
|
||||
"lowerStartCamelObject": stringx.From(camel).UnTitle(),
|
||||
"upperStartCamelObject": camel,
|
||||
"cacheKeys": strings.Join(keys, "\r\n"),
|
||||
"autoIncrement": table.PrimaryKey.AutoIncrement,
|
||||
|
||||
33
tools/goctl/model/sql/model/ddlmodel.go
Normal file
33
tools/goctl/model/sql/model/ddlmodel.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/tal-tech/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
type (
|
||||
DDLModel struct {
|
||||
conn sqlx.SqlConn
|
||||
}
|
||||
DDL struct {
|
||||
Table string `db:"Table"`
|
||||
DDL string `db:"Create Table"`
|
||||
}
|
||||
)
|
||||
|
||||
func NewDDLModel(conn sqlx.SqlConn) *DDLModel {
|
||||
return &DDLModel{conn: conn}
|
||||
}
|
||||
|
||||
func (m *DDLModel) ShowDDL(table ...string) ([]string, error) {
|
||||
var ddl []string
|
||||
for _, t := range table {
|
||||
query := `show create table ` + t
|
||||
var resp DDL
|
||||
err := m.conn.QueryRow(&resp, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ddl = append(ddl, resp.DDL)
|
||||
}
|
||||
return ddl, nil
|
||||
}
|
||||
@@ -81,7 +81,7 @@ func Parse(ddl string) (*Table, error) {
|
||||
}
|
||||
column := index.Columns[0]
|
||||
columnName := column.Column.String()
|
||||
camelColumnName := stringx.From(columnName).Snake2Camel()
|
||||
camelColumnName := stringx.From(columnName).ToCamel()
|
||||
// by default, createTime|updateTime findOne is not used.
|
||||
if camelColumnName == "CreateTime" || camelColumnName == "UpdateTime" {
|
||||
continue
|
||||
|
||||
@@ -19,6 +19,13 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
func NewConsole(idea bool) Console {
|
||||
if idea {
|
||||
return NewIdeaConsole()
|
||||
}
|
||||
return NewColorConsole()
|
||||
}
|
||||
|
||||
func NewColorConsole() *colorConsole {
|
||||
return &colorConsole{}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,6 @@ import (
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
emptyString = ""
|
||||
)
|
||||
|
||||
type (
|
||||
String struct {
|
||||
source string
|
||||
@@ -31,15 +27,9 @@ func (s String) IsEmptyOrSpace() bool {
|
||||
}
|
||||
|
||||
func (s String) Lower() string {
|
||||
if s.IsEmptyOrSpace() {
|
||||
return s.source
|
||||
}
|
||||
return strings.ToLower(s.source)
|
||||
}
|
||||
func (s String) Upper() string {
|
||||
if s.IsEmptyOrSpace() {
|
||||
return s.source
|
||||
}
|
||||
return strings.ToUpper(s.source)
|
||||
}
|
||||
func (s String) Title() string {
|
||||
@@ -50,10 +40,7 @@ func (s String) Title() string {
|
||||
}
|
||||
|
||||
// snake->camel(upper start)
|
||||
func (s String) Snake2Camel() string {
|
||||
if s.IsEmptyOrSpace() {
|
||||
return s.source
|
||||
}
|
||||
func (s String) ToCamel() string {
|
||||
list := s.splitBy(func(r rune) bool {
|
||||
return r == '_'
|
||||
}, true)
|
||||
@@ -65,10 +52,7 @@ func (s String) Snake2Camel() string {
|
||||
}
|
||||
|
||||
// camel->snake
|
||||
func (s String) Camel2Snake() string {
|
||||
if s.IsEmptyOrSpace() {
|
||||
return s.source
|
||||
}
|
||||
func (s String) ToSnake() string {
|
||||
list := s.splitBy(func(r rune) bool {
|
||||
return unicode.IsUpper(r)
|
||||
}, false)
|
||||
@@ -80,7 +64,7 @@ func (s String) Camel2Snake() string {
|
||||
}
|
||||
|
||||
// return original string if rune is not letter at index 0
|
||||
func (s String) LowerStart() string {
|
||||
func (s String) UnTitle() string {
|
||||
if s.IsEmptyOrSpace() {
|
||||
return s.source
|
||||
}
|
||||
|
||||
@@ -17,26 +17,26 @@ func TestString_IsEmptyOrSpace(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestString_Snake2Camel(t *testing.T) {
|
||||
ret := From("____this_is_snake").Snake2Camel()
|
||||
ret := From("____this_is_snake").ToCamel()
|
||||
assert.Equal(t, "ThisIsSnake", ret)
|
||||
|
||||
ret2 := From("测试_test_Data").Snake2Camel()
|
||||
ret2 := From("测试_test_Data").ToCamel()
|
||||
assert.Equal(t, "测试TestData", ret2)
|
||||
|
||||
ret3 := From("___").Snake2Camel()
|
||||
ret3 := From("___").ToCamel()
|
||||
assert.Equal(t, "", ret3)
|
||||
|
||||
ret4 := From("testData_").Snake2Camel()
|
||||
ret4 := From("testData_").ToCamel()
|
||||
assert.Equal(t, "TestData", ret4)
|
||||
|
||||
ret5 := From("testDataTestData").Snake2Camel()
|
||||
ret5 := From("testDataTestData").ToCamel()
|
||||
assert.Equal(t, "TestDataTestData", ret5)
|
||||
}
|
||||
|
||||
func TestString_Camel2Snake(t *testing.T) {
|
||||
ret := From("ThisIsCCCamel").Camel2Snake()
|
||||
ret := From("ThisIsCCCamel").ToSnake()
|
||||
assert.Equal(t, "this_is_c_c_camel", ret)
|
||||
|
||||
ret2 := From("测试Test_Data_test_data").Camel2Snake()
|
||||
ret2 := From("测试Test_Data_test_data").ToSnake()
|
||||
assert.Equal(t, "测试_test__data_test_data", ret2)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user