goctl model reactor (#15)
* reactor sql generation * reactor sql generation * add console & example * optimize unit test & add document * modify default config * remove test file * Revert "remove test file" This reverts commit 81041f9e * fix stringx.go & optimize example * remove unused code
This commit is contained in:
11
tools/goctl/model/sql/parser/error.go
Normal file
11
tools/goctl/model/sql/parser/error.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
unSupportDDL = errors.New("unexpected type")
|
||||
tableBodyIsNotFound = errors.New("create table spec not found")
|
||||
errPrimaryKey = errors.New("unexpected joint primary key")
|
||||
)
|
||||
135
tools/goctl/model/sql/parser/parser.go
Normal file
135
tools/goctl/model/sql/parser/parser.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/converter"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||
"github.com/xwb1989/sqlparser"
|
||||
)
|
||||
|
||||
const (
|
||||
none = iota
|
||||
primary
|
||||
unique
|
||||
normal
|
||||
spatial
|
||||
)
|
||||
|
||||
type (
|
||||
Table struct {
|
||||
Name stringx.String
|
||||
PrimaryKey Primary
|
||||
Fields []Field
|
||||
}
|
||||
Primary struct {
|
||||
Field
|
||||
AutoIncrement bool
|
||||
}
|
||||
Field struct {
|
||||
Name stringx.String
|
||||
DataBaseType string
|
||||
DataType string
|
||||
IsKey bool
|
||||
IsPrimaryKey bool
|
||||
Comment string
|
||||
}
|
||||
KeyType int
|
||||
)
|
||||
|
||||
func Parse(ddl string) (*Table, error) {
|
||||
stmt, err := sqlparser.ParseStrictDDL(ddl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ddlStmt, ok := stmt.(*sqlparser.DDL)
|
||||
if !ok {
|
||||
return nil, unSupportDDL
|
||||
}
|
||||
action := ddlStmt.Action
|
||||
if action != sqlparser.CreateStr {
|
||||
return nil, fmt.Errorf("expected [CREATE] action,but found: %s", action)
|
||||
}
|
||||
tableName := ddlStmt.NewName.Name.String()
|
||||
tableSpec := ddlStmt.TableSpec
|
||||
if tableSpec == nil {
|
||||
return nil, tableBodyIsNotFound
|
||||
}
|
||||
|
||||
columns := tableSpec.Columns
|
||||
indexes := tableSpec.Indexes
|
||||
|
||||
keyMap := make(map[string]KeyType)
|
||||
for _, index := range indexes {
|
||||
info := index.Info
|
||||
if info == nil {
|
||||
continue
|
||||
}
|
||||
if info.Primary {
|
||||
if len(index.Columns) > 1 {
|
||||
return nil, errPrimaryKey
|
||||
}
|
||||
keyMap[index.Columns[0].Column.String()] = primary
|
||||
continue
|
||||
}
|
||||
// can optimize
|
||||
if len(index.Columns) > 1 {
|
||||
continue
|
||||
}
|
||||
column := index.Columns[0]
|
||||
columnName := column.Column.String()
|
||||
camelColumnName := stringx.From(columnName).Snake2Camel()
|
||||
// by default, createTime|updateTime findOne is not used.
|
||||
if camelColumnName == "CreateTime" || camelColumnName == "UpdateTime" {
|
||||
continue
|
||||
}
|
||||
if info.Unique {
|
||||
keyMap[columnName] = unique
|
||||
} else if info.Spatial {
|
||||
keyMap[columnName] = spatial
|
||||
} else {
|
||||
keyMap[columnName] = normal
|
||||
}
|
||||
}
|
||||
var (
|
||||
fields []Field
|
||||
primaryKey Primary
|
||||
)
|
||||
|
||||
for _, column := range columns {
|
||||
if column == nil {
|
||||
continue
|
||||
}
|
||||
var comment string
|
||||
if column.Type.Comment != nil {
|
||||
comment = string(column.Type.Comment.Val)
|
||||
}
|
||||
dataType, err := converter.ConvertDataType(column.Type.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var field Field
|
||||
field.Name = stringx.From(column.Name.String())
|
||||
field.DataBaseType = column.Type.Type
|
||||
field.DataType = dataType
|
||||
field.Comment = comment
|
||||
key, ok := keyMap[column.Name.String()]
|
||||
if ok {
|
||||
field.IsKey = true
|
||||
field.IsPrimaryKey = key == primary
|
||||
if field.IsPrimaryKey {
|
||||
primaryKey.Field = field
|
||||
if column.Type.Autoincrement {
|
||||
primaryKey.AutoIncrement = true
|
||||
}
|
||||
}
|
||||
}
|
||||
fields = append(fields, field)
|
||||
}
|
||||
return &Table{
|
||||
Name: stringx.From(tableName),
|
||||
PrimaryKey: primaryKey,
|
||||
Fields: fields,
|
||||
}, nil
|
||||
|
||||
}
|
||||
27
tools/goctl/model/sql/parser/parser_test.go
Normal file
27
tools/goctl/model/sql/parser/parser_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParsePlainText(t *testing.T) {
|
||||
_, err := Parse("plain text")
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestParseSelect(t *testing.T) {
|
||||
_, err := Parse("select * from user")
|
||||
assert.Equal(t, unSupportDDL, err)
|
||||
}
|
||||
|
||||
func TestParseCreateTable(t *testing.T) {
|
||||
_, err := Parse("CREATE TABLE `user_snake` (\n `id` bigint(10) NOT NULL AUTO_INCREMENT,\n `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',\n `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',\n `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',\n `gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',\n `nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',\n `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n UNIQUE KEY `name_index` (`name`),\n KEY `mobile_index` (`mobile`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;")
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestParseCreateTable2(t *testing.T) {
|
||||
_, err := Parse("create table `user_snake` (\n `id` bigint(10) NOT NULL AUTO_INCREMENT,\n `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',\n `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',\n `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',\n `gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',\n `nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',\n `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n UNIQUE KEY `name_index` (`name`),\n KEY `mobile_index` (`mobile`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;")
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
Reference in New Issue
Block a user