Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43e712d86a | ||
|
|
4db20677f7 | ||
|
|
6887fb22de | ||
|
|
50fbdbcfd7 | ||
|
|
c77b8489d7 | ||
|
|
eca4ed2cc0 |
@@ -146,15 +146,15 @@ func EcbEncryptBase64(key, src string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getKeyBytes(key string) ([]byte, error) {
|
func getKeyBytes(key string) ([]byte, error) {
|
||||||
if len(key) > 32 {
|
if len(key) <= 32 {
|
||||||
if keyBytes, err := base64.StdEncoding.DecodeString(key); err != nil {
|
return []byte(key), nil
|
||||||
return nil, err
|
|
||||||
} else {
|
|
||||||
return keyBytes, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte(key), nil
|
if keyBytes, err := base64.StdEncoding.DecodeString(key); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return keyBytes, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
|
func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
|
||||||
|
|||||||
64
core/codec/aesecb_test.go
Normal file
64
core/codec/aesecb_test.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package codec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAesEcb(t *testing.T) {
|
||||||
|
var (
|
||||||
|
key = []byte("q4t7w!z%C*F-JaNdRgUjXn2r5u8x/A?D")
|
||||||
|
val = []byte("hello")
|
||||||
|
badKey1 = []byte("aaaaaaaaa")
|
||||||
|
// more than 32 chars
|
||||||
|
badKey2 = []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
||||||
|
)
|
||||||
|
_, err := EcbEncrypt(badKey1, val)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
_, err = EcbEncrypt(badKey2, val)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
dst, err := EcbEncrypt(key, val)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
_, err = EcbDecrypt(badKey1, dst)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
_, err = EcbDecrypt(badKey2, dst)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
_, err = EcbDecrypt(key, val)
|
||||||
|
// not enough block, just nil
|
||||||
|
assert.Nil(t, err)
|
||||||
|
src, err := EcbDecrypt(key, dst)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, src)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAesEcbBase64(t *testing.T) {
|
||||||
|
const (
|
||||||
|
val = "hello"
|
||||||
|
badKey1 = "aaaaaaaaa"
|
||||||
|
// more than 32 chars
|
||||||
|
badKey2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
)
|
||||||
|
var key = []byte("q4t7w!z%C*F-JaNdRgUjXn2r5u8x/A?D")
|
||||||
|
b64Key := base64.StdEncoding.EncodeToString(key)
|
||||||
|
b64Val := base64.StdEncoding.EncodeToString([]byte(val))
|
||||||
|
_, err := EcbEncryptBase64(badKey1, val)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
_, err = EcbEncryptBase64(badKey2, val)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
_, err = EcbEncryptBase64(b64Key, val)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
dst, err := EcbEncryptBase64(b64Key, b64Val)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
_, err = EcbDecryptBase64(badKey1, dst)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
_, err = EcbDecryptBase64(badKey2, dst)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
_, err = EcbDecryptBase64(b64Key, val)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
src, err := EcbDecryptBase64(b64Key, dst)
|
||||||
|
b, err := base64.StdEncoding.DecodeString(src)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, string(b))
|
||||||
|
}
|
||||||
@@ -51,7 +51,7 @@ func NewPeriodicalExecutor(interval time.Duration, container TaskContainer) *Per
|
|||||||
container: container,
|
container: container,
|
||||||
confirmChan: make(chan lang.PlaceholderType),
|
confirmChan: make(chan lang.PlaceholderType),
|
||||||
newTicker: func(d time.Duration) timex.Ticker {
|
newTicker: func(d time.Duration) timex.Ticker {
|
||||||
return timex.NewTicker(interval)
|
return timex.NewTicker(d)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
proc.AddShutdownListener(func() {
|
proc.AddShutdownListener(func() {
|
||||||
|
|||||||
@@ -161,17 +161,10 @@ GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/
|
|||||||
|
|
||||||
[https://www.yuque.com/tal-tech/go-zero](https://www.yuque.com/tal-tech/go-zero)
|
[https://www.yuque.com/tal-tech/go-zero](https://www.yuque.com/tal-tech/go-zero)
|
||||||
|
|
||||||
* awesome 系列(全部收录于『微服务实践』公众号)
|
* awesome 系列(更多文章见『微服务实践』公众号)
|
||||||
* [快速构建高并发微服务](https://github.com/tal-tech/zero-doc/blob/main/doc/shorturl.md)
|
* [快速构建高并发微服务](https://github.com/tal-tech/zero-doc/blob/main/doc/shorturl.md)
|
||||||
* [快速构建高并发微服务 - 多 RPC 版](https://github.com/tal-tech/zero-doc/blob/main/docs/zero/bookstore.md)
|
* [快速构建高并发微服务 - 多 RPC 版](https://github.com/tal-tech/zero-doc/blob/main/docs/zero/bookstore.md)
|
||||||
* [goctl 使用帮助](https://github.com/tal-tech/zero-doc/blob/main/doc/goctl.md)
|
* [goctl 使用帮助](https://github.com/tal-tech/zero-doc/blob/main/doc/goctl.md)
|
||||||
* [通过 MapReduce 降低服务响应时间](https://github.com/tal-tech/zero-doc/blob/main/doc/mapreduce.md)
|
|
||||||
* [关键字替换和敏感词过滤工具](https://github.com/tal-tech/zero-doc/blob/main/doc/keywords.md)
|
|
||||||
* [进程内缓存使用方法](https://github.com/tal-tech/zero-doc/blob/main/doc/collection.md)
|
|
||||||
* [防止缓存击穿之进程内共享调用](https://github.com/tal-tech/zero-doc/blob/main/doc/sharedcalls.md)
|
|
||||||
* [基于 prometheus 的微服务指标监控](https://github.com/tal-tech/zero-doc/blob/main/doc/metric.md)
|
|
||||||
* [文本序列化和反序列化](https://github.com/tal-tech/zero-doc/blob/main/doc/mapping.md)
|
|
||||||
* [快速构建 jwt 鉴权认证](https://github.com/tal-tech/zero-doc/blob/main/doc/jwt.md)
|
|
||||||
|
|
||||||
* 精选 `goctl` 插件
|
* 精选 `goctl` 插件
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ func getParentPackage(dir string) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.ToSlash(filepath.Join(projectCtx.Path, strings.TrimPrefix(projectCtx.WorkDir, projectCtx.Dir))), nil
|
return filepath.ToSlash(filepath.Join(projectCtx.Path, strings.TrimPrefix(projectCtx.WorkDir, projectCtx.Dir))), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,6 +83,7 @@ func writeProperty(writer io.Writer, name, tag, comment string, tp spec.Type, in
|
|||||||
} else {
|
} else {
|
||||||
_, err = fmt.Fprintf(writer, "%s %s %s\n", strings.Title(name), tp.Name(), tag)
|
_, err = fmt.Fprintf(writer, "%s %s %s\n", strings.Title(name), tp.Name(), tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +112,7 @@ func getMiddleware(api *spec.ApiSpec) []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.KeysStr()
|
return result.KeysStr()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +130,15 @@ func responseGoTypeName(r spec.Route, pkg ...string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return golangExpr(r.ResponseType, pkg...)
|
resp := golangExpr(r.ResponseType, pkg...)
|
||||||
|
switch r.ResponseType.(type) {
|
||||||
|
case spec.DefineStruct:
|
||||||
|
if !strings.HasPrefix(resp, "*") {
|
||||||
|
return "*" + resp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestGoTypeName(r spec.Route, pkg ...string) string {
|
func requestGoTypeName(r spec.Route, pkg ...string) string {
|
||||||
|
|||||||
@@ -339,5 +339,6 @@ func formatSource(source string) string {
|
|||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ func getImports(api *spec.ApiSpec, packetName string) string {
|
|||||||
if len(allTypes) > 0 {
|
if len(allTypes) > 0 {
|
||||||
fmt.Fprintf(&builder, "import com.xhb.logic.http.packet.%s.model.*;\n", packetName)
|
fmt.Fprintf(&builder, "import com.xhb.logic.http.packet.%s.model.*;\n", packetName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ func (p parser) convert2Spec() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.fillService()
|
return p.fillService()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +189,7 @@ func (p parser) astTypeToSpec(in ast.DataType) spec.Type {
|
|||||||
return spec.PointerType{RawName: v.PointerExpr.Text(), Type: spec.DefineStruct{RawName: raw}}
|
return spec.PointerType{RawName: v.PointerExpr.Text(), Type: spec.DefineStruct{RawName: raw}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Sprintf("unspported type %+v", in))
|
panic(fmt.Sprintf("unspported type %+v", in))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,6 +205,7 @@ func (p parser) commentExprs(comment ast.Expr) string {
|
|||||||
if comment == nil {
|
if comment == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return comment.Text()
|
return comment.Text()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,5 +313,6 @@ func (p parser) fillRouteType(route *spec.Route) error {
|
|||||||
route.ResponseType = *tp
|
route.ResponseType = *tp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ func (r Route) GetAnnotation(key string) string {
|
|||||||
if r.Annotation.Properties == nil {
|
if r.Annotation.Properties == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.Annotation.Properties[key]
|
return r.Annotation.Properties[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,6 +178,7 @@ func (g Group) GetAnnotation(key string) string {
|
|||||||
if g.Annotation.Properties == nil {
|
if g.Annotation.Properties == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return g.Annotation.Properties[key]
|
return g.Annotation.Properties[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
BuildVersion = "1.1.3"
|
BuildVersion = "1.1.4"
|
||||||
commands = []cli.Command{
|
commands = []cli.Command{
|
||||||
{
|
{
|
||||||
Name: "upgrade",
|
Name: "upgrade",
|
||||||
|
|||||||
@@ -23,10 +23,12 @@ func ToMap(in interface{}) map[string]interface{} {
|
|||||||
if v.Kind() == reflect.Ptr {
|
if v.Kind() == reflect.Ptr {
|
||||||
v = v.Elem()
|
v = v.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only accept structs
|
// we only accept structs
|
||||||
if v.Kind() != reflect.Struct {
|
if v.Kind() != reflect.Struct {
|
||||||
panic(fmt.Errorf("ToMap only accepts structs; got %T", v))
|
panic(fmt.Errorf("ToMap only accepts structs; got %T", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
typ := v.Type()
|
typ := v.Type()
|
||||||
for i := 0; i < v.NumField(); i++ {
|
for i := 0; i < v.NumField(); i++ {
|
||||||
// gets us a StructField
|
// gets us a StructField
|
||||||
@@ -43,6 +45,7 @@ func ToMap(in interface{}) map[string]interface{} {
|
|||||||
out[tagv] = current
|
out[tagv] = current
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,10 +56,12 @@ func FieldNames(in interface{}) []string {
|
|||||||
if v.Kind() == reflect.Ptr {
|
if v.Kind() == reflect.Ptr {
|
||||||
v = v.Elem()
|
v = v.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only accept structs
|
// we only accept structs
|
||||||
if v.Kind() != reflect.Struct {
|
if v.Kind() != reflect.Struct {
|
||||||
panic(fmt.Errorf("ToMap only accepts structs; got %T", v))
|
panic(fmt.Errorf("ToMap only accepts structs; got %T", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
typ := v.Type()
|
typ := v.Type()
|
||||||
for i := 0; i < v.NumField(); i++ {
|
for i := 0; i < v.NumField(); i++ {
|
||||||
// gets us a StructField
|
// gets us a StructField
|
||||||
@@ -67,6 +72,7 @@ func FieldNames(in interface{}) []string {
|
|||||||
out = append(out, fi.Name)
|
out = append(out, fi.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,10 +82,12 @@ func RawFieldNames(in interface{}) []string {
|
|||||||
if v.Kind() == reflect.Ptr {
|
if v.Kind() == reflect.Ptr {
|
||||||
v = v.Elem()
|
v = v.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only accept structs
|
// we only accept structs
|
||||||
if v.Kind() != reflect.Struct {
|
if v.Kind() != reflect.Struct {
|
||||||
panic(fmt.Errorf("ToMap only accepts structs; got %T", v))
|
panic(fmt.Errorf("ToMap only accepts structs; got %T", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
typ := v.Type()
|
typ := v.Type()
|
||||||
for i := 0; i < v.NumField(); i++ {
|
for i := 0; i < v.NumField(); i++ {
|
||||||
// gets us a StructField
|
// gets us a StructField
|
||||||
@@ -90,5 +98,6 @@ func RawFieldNames(in interface{}) []string {
|
|||||||
out = append(out, fmt.Sprintf(`"%s"`, fi.Name))
|
out = append(out, fmt.Sprintf(`"%s"`, fi.Name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,34 +8,32 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type mockedUser struct {
|
||||||
User struct {
|
// 自增id
|
||||||
// 自增id
|
Id string `db:"id" json:"id,omitempty"`
|
||||||
Id string `db:"id" json:"id,omitempty"`
|
// 姓名
|
||||||
// 姓名
|
UserName string `db:"user_name" json:"userName,omitempty"`
|
||||||
UserName string `db:"user_name" json:"userName,omitempty"`
|
// 1男,2女
|
||||||
// 1男,2女
|
Sex int `db:"sex" json:"sex,omitempty"`
|
||||||
Sex int `db:"sex" json:"sex,omitempty"`
|
Uuid string `db:"uuid" uuid:"uuid,omitempty"`
|
||||||
|
Age int `db:"age" json:"age"`
|
||||||
|
}
|
||||||
|
|
||||||
Uuid string `db:"uuid" uuid:"uuid,omitempty"`
|
var (
|
||||||
|
userFieldsWithRawStringQuote = RawFieldNames(mockedUser{})
|
||||||
Age int `db:"age" json:"age"`
|
userFieldsWithoutRawStringQuote = FieldNames(mockedUser{})
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var userFieldsWithRawStringQuote = RawFieldNames(User{})
|
|
||||||
var userFieldsWithoutRawStringQuote = FieldNames(User{})
|
|
||||||
|
|
||||||
func TestFieldNames(t *testing.T) {
|
func TestFieldNames(t *testing.T) {
|
||||||
t.Run("old", func(t *testing.T) {
|
t.Run("old", func(t *testing.T) {
|
||||||
var u User
|
var u mockedUser
|
||||||
out := FieldNames(&u)
|
out := FieldNames(&u)
|
||||||
expected := []string{"id", "user_name", "sex", "uuid", "age"}
|
expected := []string{"id", "user_name", "sex", "uuid", "age"}
|
||||||
assert.Equal(t, expected, out)
|
assert.Equal(t, expected, out)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("new", func(t *testing.T) {
|
t.Run("new", func(t *testing.T) {
|
||||||
var u User
|
var u mockedUser
|
||||||
out := RawFieldNames(&u)
|
out := RawFieldNames(&u)
|
||||||
expected := []string{"`id`", "`user_name`", "`sex`", "`uuid`", "`age`"}
|
expected := []string{"`id`", "`user_name`", "`sex`", "`uuid`", "`age`"}
|
||||||
assert.Equal(t, expected, out)
|
assert.Equal(t, expected, out)
|
||||||
@@ -43,7 +41,7 @@ func TestFieldNames(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNewEq(t *testing.T) {
|
func TestNewEq(t *testing.T) {
|
||||||
u := &User{
|
u := &mockedUser{
|
||||||
Id: "123456",
|
Id: "123456",
|
||||||
UserName: "wahaha",
|
UserName: "wahaha",
|
||||||
}
|
}
|
||||||
@@ -55,7 +53,7 @@ func TestNewEq(t *testing.T) {
|
|||||||
|
|
||||||
// @see https://github.com/go-xorm/builder
|
// @see https://github.com/go-xorm/builder
|
||||||
func TestBuilderSql(t *testing.T) {
|
func TestBuilderSql(t *testing.T) {
|
||||||
u := &User{
|
u := &mockedUser{
|
||||||
Id: "123123",
|
Id: "123123",
|
||||||
}
|
}
|
||||||
fields := RawFieldNames(u)
|
fields := RawFieldNames(u)
|
||||||
@@ -96,7 +94,7 @@ func TestBuildSqlDefaultValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBuilderSqlIn(t *testing.T) {
|
func TestBuilderSqlIn(t *testing.T) {
|
||||||
u := &User{
|
u := &mockedUser{
|
||||||
Age: 18,
|
Age: 18,
|
||||||
}
|
}
|
||||||
gtU := NewGt(u)
|
gtU := NewGt(u)
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errNotMatched = errors.New("sql not matched")
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
flagSrc = "src"
|
flagSrc = "src"
|
||||||
flagDir = "dir"
|
flagDir = "dir"
|
||||||
@@ -29,6 +27,8 @@ const (
|
|||||||
flagStyle = "style"
|
flagStyle = "style"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errNotMatched = errors.New("sql not matched")
|
||||||
|
|
||||||
func MysqlDDL(ctx *cli.Context) error {
|
func MysqlDDL(ctx *cli.Context) error {
|
||||||
src := ctx.String(flagSrc)
|
src := ctx.String(flagSrc)
|
||||||
dir := ctx.String(flagDir)
|
dir := ctx.String(flagDir)
|
||||||
@@ -39,6 +39,7 @@ func MysqlDDL(ctx *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return fromDDl(src, dir, cfg, cache, idea)
|
return fromDDl(src, dir, cfg, cache, idea)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,13 +83,13 @@ func fromDDl(src, dir string, cfg *config.Config, cache, idea bool) error {
|
|||||||
|
|
||||||
source = append(source, string(data))
|
source = append(source, string(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log))
|
generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = generator.StartFromDDL(strings.Join(source, "\n"), cache)
|
return generator.StartFromDDL(strings.Join(source, "\n"), cache)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func fromDataSource(url, pattern, dir string, cfg *config.Config, cache, idea bool) error {
|
func fromDataSource(url, pattern, dir string, cfg *config.Config, cache, idea bool) error {
|
||||||
@@ -144,6 +145,5 @@ func fromDataSource(url, pattern, dir string, cfg *config.Config, cache, idea bo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = generator.StartFromInformationSchema(dsn.DBName, matchTables, cache)
|
return generator.StartFromInformationSchema(dsn.DBName, matchTables, cache)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var sql = "-- 用户表 --\nCREATE TABLE `user` (\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 UNIQUE KEY `mobile_index` (`mobile`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;\n\n"
|
var (
|
||||||
var cfg = &config.Config{
|
sql = "-- 用户表 --\nCREATE TABLE `user` (\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 UNIQUE KEY `mobile_index` (`mobile`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;\n\n"
|
||||||
NamingFormat: "gozero",
|
cfg = &config.Config{
|
||||||
}
|
NamingFormat: "gozero",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func TestFromDDl(t *testing.T) {
|
func TestFromDDl(t *testing.T) {
|
||||||
err := fromDDl("./user.sql", t.TempDir(), cfg, true, false)
|
err := fromDDl("./user.sql", t.TempDir(), cfg, true, false)
|
||||||
|
|||||||
@@ -5,41 +5,39 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var commonMysqlDataTypeMap = map[string]string{
|
||||||
commonMysqlDataTypeMap = map[string]string{
|
// For consistency, all integer types are converted to int64
|
||||||
// For consistency, all integer types are converted to int64
|
// number
|
||||||
// number
|
"bool": "int64",
|
||||||
"bool": "int64",
|
"boolean": "int64",
|
||||||
"boolean": "int64",
|
"tinyint": "int64",
|
||||||
"tinyint": "int64",
|
"smallint": "int64",
|
||||||
"smallint": "int64",
|
"mediumint": "int64",
|
||||||
"mediumint": "int64",
|
"int": "int64",
|
||||||
"int": "int64",
|
"integer": "int64",
|
||||||
"integer": "int64",
|
"bigint": "int64",
|
||||||
"bigint": "int64",
|
"float": "float64",
|
||||||
"float": "float64",
|
"double": "float64",
|
||||||
"double": "float64",
|
"decimal": "float64",
|
||||||
"decimal": "float64",
|
// date&time
|
||||||
// date&time
|
"date": "time.Time",
|
||||||
"date": "time.Time",
|
"datetime": "time.Time",
|
||||||
"datetime": "time.Time",
|
"timestamp": "time.Time",
|
||||||
"timestamp": "time.Time",
|
"time": "string",
|
||||||
"time": "string",
|
"year": "int64",
|
||||||
"year": "int64",
|
// string
|
||||||
// string
|
"char": "string",
|
||||||
"char": "string",
|
"varchar": "string",
|
||||||
"varchar": "string",
|
"binary": "string",
|
||||||
"binary": "string",
|
"varbinary": "string",
|
||||||
"varbinary": "string",
|
"tinytext": "string",
|
||||||
"tinytext": "string",
|
"text": "string",
|
||||||
"text": "string",
|
"mediumtext": "string",
|
||||||
"mediumtext": "string",
|
"longtext": "string",
|
||||||
"longtext": "string",
|
"enum": "string",
|
||||||
"enum": "string",
|
"set": "string",
|
||||||
"set": "string",
|
"json": "string",
|
||||||
"json": "string",
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func ConvertDataType(dataBaseType string, isDefaultNull bool) (string, error) {
|
func ConvertDataType(dataBaseType string, isDefaultNull bool) (string, error) {
|
||||||
tp, ok := commonMysqlDataTypeMap[strings.ToLower(dataBaseType)]
|
tp, ok := commonMysqlDataTypeMap[strings.ToLower(dataBaseType)]
|
||||||
|
|||||||
@@ -58,5 +58,6 @@ func genDelete(table Table, withCache bool) (string, string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return output.String(), deleteMethodOut.String(), nil
|
return output.String(), deleteMethodOut.String(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
func genFields(fields []parser.Field) (string, error) {
|
func genFields(fields []parser.Field) (string, error) {
|
||||||
var list []string
|
var list []string
|
||||||
|
|
||||||
for _, field := range fields {
|
for _, field := range fields {
|
||||||
result, err := genField(field)
|
result, err := genField(field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -18,6 +19,7 @@ func genFields(fields []parser.Field) (string, error) {
|
|||||||
|
|
||||||
list = append(list, result)
|
list = append(list, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.Join(list, "\n"), nil
|
return strings.Join(list, "\n"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,5 +44,6 @@ func genFindOne(table Table, withCache bool) (string, string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return output.String(), findOneMethod.String(), nil
|
return output.String(), findOneMethod.String(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
defaultGenerator struct {
|
defaultGenerator struct {
|
||||||
//source string
|
// source string
|
||||||
dir string
|
dir string
|
||||||
console.Console
|
console.Console
|
||||||
pkg string
|
pkg string
|
||||||
@@ -57,6 +57,7 @@ func NewDefaultGenerator(dir string, cfg *config.Config, opt ...Option) (*defaul
|
|||||||
for _, fn := range optionList {
|
for _, fn := range optionList {
|
||||||
fn(generator)
|
fn(generator)
|
||||||
}
|
}
|
||||||
|
|
||||||
return generator, nil
|
return generator, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +97,7 @@ func (g *defaultGenerator) StartFromInformationSchema(db string, columns map[str
|
|||||||
|
|
||||||
m[table.Name.Source()] = code
|
m[table.Name.Source()] = code
|
||||||
}
|
}
|
||||||
|
|
||||||
return g.createFile(m)
|
return g.createFile(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +132,7 @@ func (g *defaultGenerator) createFile(modelList map[string]string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate error file
|
// generate error file
|
||||||
varFilename, err := format.FileNamingFormat(g.cfg.NamingFormat, "vars")
|
varFilename, err := format.FileNamingFormat(g.cfg.NamingFormat, "vars")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -168,16 +171,15 @@ func (g *defaultGenerator) genFromDDL(source string, withCache bool) (map[string
|
|||||||
}
|
}
|
||||||
m[table.Name.Source()] = code
|
m[table.Name.Source()] = code
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type Table struct {
|
||||||
Table struct {
|
parser.Table
|
||||||
parser.Table
|
CacheKey map[string]Key
|
||||||
CacheKey map[string]Key
|
ContainsUniqueKey bool
|
||||||
ContainsUniqueKey bool
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, error) {
|
func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, error) {
|
||||||
if len(in.PrimaryKey.Name.Source()) == 0 {
|
if len(in.PrimaryKey.Name.Source()) == 0 {
|
||||||
@@ -292,5 +294,6 @@ func wrapWithRawString(v string) string {
|
|||||||
} else if len(v) == 1 {
|
} else if len(v) == 1 {
|
||||||
v = v + "`"
|
v = v + "`"
|
||||||
}
|
}
|
||||||
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,20 +8,18 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
// tableName:user
|
||||||
// tableName:user
|
// {{prefix}}=cache
|
||||||
// {{prefix}}=cache
|
// key:id
|
||||||
// key:id
|
type Key struct {
|
||||||
Key struct {
|
VarExpression string // cacheUserIdPrefix = "cache#User#id#"
|
||||||
VarExpression string // cacheUserIdPrefix = "cache#User#id#"
|
Left string // cacheUserIdPrefix
|
||||||
Left string // cacheUserIdPrefix
|
Right string // cache#user#id#
|
||||||
Right string // cache#user#id#
|
Variable string // userIdKey
|
||||||
Variable string // userIdKey
|
KeyExpression string // userIdKey: = fmt.Sprintf("cache#user#id#%v", userId)
|
||||||
KeyExpression string // userIdKey: = fmt.Sprintf("cache#user#id#%v", userId)
|
DataKeyExpression string // userIdKey: = fmt.Sprintf("cache#user#id#%v", data.userId)
|
||||||
DataKeyExpression string // userIdKey: = fmt.Sprintf("cache#user#id#%v", data.userId)
|
RespKeyExpression string // userIdKey: = fmt.Sprintf("cache#user#id#%v", resp.userId)
|
||||||
RespKeyExpression string // userIdKey: = fmt.Sprintf("cache#user#id#%v", resp.userId)
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// key-数据库原始字段名,value-缓存key相关数据
|
// key-数据库原始字段名,value-缓存key相关数据
|
||||||
func genCacheKeys(table parser.Table) (map[string]Key, error) {
|
func genCacheKeys(table parser.Table) (map[string]Key, error) {
|
||||||
@@ -42,6 +40,7 @@ func genCacheKeys(table parser.Table) (map[string]Key, error) {
|
|||||||
if strings.ToLower(lowerStartCamelTableName) == strings.ToLower(camelFieldName) {
|
if strings.ToLower(lowerStartCamelTableName) == strings.ToLower(camelFieldName) {
|
||||||
variable = fmt.Sprintf("%sKey", lowerStartCamelTableName)
|
variable = fmt.Sprintf("%sKey", lowerStartCamelTableName)
|
||||||
}
|
}
|
||||||
|
|
||||||
m[field.Name.Source()] = Key{
|
m[field.Name.Source()] = Key{
|
||||||
VarExpression: fmt.Sprintf(`%s = "%s"`, left, right),
|
VarExpression: fmt.Sprintf(`%s = "%s"`, left, right),
|
||||||
Left: left,
|
Left: left,
|
||||||
@@ -53,5 +52,6 @@ func genCacheKeys(table parser.Table) (map[string]Key, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,5 +68,4 @@ func TestGenCacheKeys(t *testing.T) {
|
|||||||
assert.Equal(t, fmt.Sprintf(`user%sKey`, name.ToCamel()), key.Variable)
|
assert.Equal(t, fmt.Sprintf(`user%sKey`, name.ToCamel()), key.Variable)
|
||||||
assert.Equal(t, `user`+name.ToCamel()+`Key := fmt.Sprintf("%s%v", cacheUser`+name.ToCamel()+`Prefix,`+name.Untitle()+`)`, key.KeyExpression)
|
assert.Equal(t, `user`+name.ToCamel()+`Key := fmt.Sprintf("%s%v", cacheUser`+name.ToCamel()+`Prefix,`+name.Untitle()+`)`, key.KeyExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package gen
|
package gen
|
||||||
|
|
||||||
import (
|
import "regexp"
|
||||||
"regexp"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (g *defaultGenerator) split(source string) []string {
|
func (g *defaultGenerator) split(source string) []string {
|
||||||
reg := regexp.MustCompile(createTableFlag)
|
reg := regexp.MustCompile(createTableFlag)
|
||||||
index := reg.FindAllStringIndex(source, -1)
|
index := reg.FindAllStringIndex(source, -1)
|
||||||
list := make([]string, 0)
|
list := make([]string, 0)
|
||||||
|
|
||||||
for i := len(index) - 1; i >= 0; i-- {
|
for i := len(index) - 1; i >= 0; i-- {
|
||||||
subIndex := index[i]
|
subIndex := index[i]
|
||||||
if len(subIndex) == 0 {
|
if len(subIndex) == 0 {
|
||||||
@@ -18,5 +17,6 @@ func (g *defaultGenerator) split(source string) []string {
|
|||||||
list = append(list, ddl)
|
list = append(list, ddl)
|
||||||
source = source[:start]
|
source = source[:start]
|
||||||
}
|
}
|
||||||
|
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,16 +9,15 @@ func genTag(in string) (string, error) {
|
|||||||
if in == "" {
|
if in == "" {
|
||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := util.LoadTemplate(category, tagTemplateFile, template.Tag)
|
text, err := util.LoadTemplate(category, tagTemplateFile, template.Tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
output, err := util.With("tag").
|
output, err := util.With("tag").Parse(text).Execute(map[string]interface{}{
|
||||||
Parse(text).
|
"field": in,
|
||||||
Execute(map[string]interface{}{
|
})
|
||||||
"field": in,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ func RevertTemplate(name string) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%s: no such file name", name)
|
return fmt.Errorf("%s: no such file name", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return util.CreateTemplate(category, name, content)
|
return util.CreateTemplate(category, name, content)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,5 +80,6 @@ func Update() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return util.InitTemplates(category, templates)
|
return util.InitTemplates(category, templates)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,14 @@ func genUpdate(table Table, withCache bool) (string, string, error) {
|
|||||||
if camel == "CreateTime" || camel == "UpdateTime" {
|
if camel == "CreateTime" || camel == "UpdateTime" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if field.IsPrimaryKey {
|
if field.IsPrimaryKey {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
expressionValues = append(expressionValues, "data."+camel)
|
expressionValues = append(expressionValues, "data."+camel)
|
||||||
}
|
}
|
||||||
|
|
||||||
expressionValues = append(expressionValues, "data."+table.PrimaryKey.Name.ToCamel())
|
expressionValues = append(expressionValues, "data."+table.PrimaryKey.Name.ToCamel())
|
||||||
camelTableName := table.Name.ToCamel()
|
camelTableName := table.Name.ToCamel()
|
||||||
text, err := util.LoadTemplate(category, updateTemplateFile, template.Update)
|
text, err := util.LoadTemplate(category, updateTemplateFile, template.Update)
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import "github.com/tal-tech/go-zero/core/stores/sqlx"
|
||||||
"github.com/tal-tech/go-zero/core/stores/sqlx"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
InformationSchemaModel struct {
|
InformationSchemaModel struct {
|
||||||
conn sqlx.SqlConn
|
conn sqlx.SqlConn
|
||||||
}
|
}
|
||||||
|
|
||||||
Column struct {
|
Column struct {
|
||||||
Name string `db:"COLUMN_NAME"`
|
Name string `db:"COLUMN_NAME"`
|
||||||
DataType string `db:"DATA_TYPE"`
|
DataType string `db:"DATA_TYPE"`
|
||||||
|
|||||||
@@ -161,10 +161,26 @@ func NewPlugin() (*Plugin, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(content, &plugin)
|
|
||||||
|
var info struct {
|
||||||
|
ApiFilePath string
|
||||||
|
Style string
|
||||||
|
Dir string
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(content, &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugin.ApiFilePath = info.ApiFilePath
|
||||||
|
plugin.Style = info.Style
|
||||||
|
plugin.Dir = info.Dir
|
||||||
|
api, err := parser.Parse(info.ApiFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.Api = api
|
||||||
return &plugin, nil
|
return &plugin, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user