From 6c624a6ed0b940e522b5362439986a24420079ab Mon Sep 17 00:00:00 2001 From: anqiansong Date: Fri, 8 Jan 2021 12:01:21 +0800 Subject: [PATCH] Feature model fix (#362) * fix sql builderx adding raw string quotation marks incompatibility bug * add unit test * remove comments * fix sql builderx adding raw string quotation marks incompatibility bug --- tools/goctl/model/sql/builderx/builder.go | 28 ++++++++++- .../goctl/model/sql/builderx/builder_test.go | 50 +++++++++++++------ tools/goctl/model/sql/example/makefile | 10 ++-- tools/goctl/model/sql/gen/gen_test.go | 2 +- tools/goctl/model/sql/template/vars.go | 2 +- .../model/sql/test/model/studentmodel.go | 2 +- tools/goctl/model/sql/test/model/usermodel.go | 4 +- 7 files changed, 72 insertions(+), 26 deletions(-) diff --git a/tools/goctl/model/sql/builderx/builder.go b/tools/goctl/model/sql/builderx/builder.go index 01ce067c..803f5b42 100644 --- a/tools/goctl/model/sql/builderx/builder.go +++ b/tools/goctl/model/sql/builderx/builder.go @@ -46,6 +46,7 @@ func ToMap(in interface{}) map[string]interface{} { return out } +// deprecated: use RawFieldNames instead automaticly while model generating after goctl version v1.1.0 func FieldNames(in interface{}) []string { out := make([]string, 0) v := reflect.ValueOf(in) @@ -61,9 +62,32 @@ func FieldNames(in interface{}) []string { // gets us a StructField fi := typ.Field(i) if tagv := fi.Tag.Get(dbTag); tagv != "" { - out = append(out, fmt.Sprintf("`%v`", tagv)) + out = append(out, tagv) } else { - out = append(out, fmt.Sprintf("`%v`", fi.Name)) + out = append(out, fi.Name) + } + } + return out +} + +func RawFieldNames(in interface{}) []string { + out := make([]string, 0) + v := reflect.ValueOf(in) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + // we only accept structs + 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++ { + // gets us a StructField + fi := typ.Field(i) + if tagv := fi.Tag.Get(dbTag); tagv != "" { + out = append(out, fmt.Sprintf("`%s`", tagv)) + } else { + out = append(out, fmt.Sprintf(`"%s"`, fi.Name)) } } return out diff --git a/tools/goctl/model/sql/builderx/builder_test.go b/tools/goctl/model/sql/builderx/builder_test.go index 1bbba6a5..09f9bc47 100644 --- a/tools/goctl/model/sql/builderx/builder_test.go +++ b/tools/goctl/model/sql/builderx/builder_test.go @@ -23,13 +23,23 @@ type ( } ) -var userFields = FieldNames(User{}) +var userFieldsWithRawStringQuote = RawFieldNames(User{}) +var userFieldsWithoutRawStringQuote = FieldNames(User{}) func TestFieldNames(t *testing.T) { - var u User - out := FieldNames(&u) - actual := []string{"`id`", "`user_name`", "`sex`", "`uuid`", "`age`"} - assert.Equal(t, out, actual) + t.Run("old", func(t *testing.T) { + var u User + out := FieldNames(&u) + expected := []string{"id", "user_name", "sex", "uuid", "age"} + assert.Equal(t, expected, out) + }) + + t.Run("new", func(t *testing.T) { + var u User + out := RawFieldNames(&u) + expected := []string{"`id`", "`user_name`", "`sex`", "`uuid`", "`age`"} + assert.Equal(t, expected, out) + }) } func TestNewEq(t *testing.T) { @@ -48,7 +58,7 @@ func TestBuilderSql(t *testing.T) { u := &User{ Id: "123123", } - fields := FieldNames(u) + fields := RawFieldNames(u) eq := NewEq(u) sql, args, err := builder.Select(fields...).From("user").Where(eq).ToSQL() fmt.Println(sql, args, err) @@ -64,13 +74,25 @@ func TestBuildSqlDefaultValue(t *testing.T) { eq["age"] = 0 eq["user_name"] = "" - sql, args, err := builder.Select(userFields...).From("user").Where(eq).ToSQL() - fmt.Println(sql, args, err) + t.Run("raw", func(t *testing.T) { + sql, args, err := builder.Select(userFieldsWithRawStringQuote...).From("user").Where(eq).ToSQL() + fmt.Println(sql, args, err) - actualSql := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE age=? AND user_name=?" - actualArgs := []interface{}{0, ""} - assert.Equal(t, sql, actualSql) - assert.Equal(t, args, actualArgs) + actualSql := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE age=? AND user_name=?" + actualArgs := []interface{}{0, ""} + assert.Equal(t, sql, actualSql) + assert.Equal(t, args, actualArgs) + }) + + t.Run("withour raw quote", func(t *testing.T) { + sql, args, err := builder.Select(userFieldsWithoutRawStringQuote...).From("user").Where(eq).ToSQL() + fmt.Println(sql, args, err) + + actualSql := "SELECT id,user_name,sex,uuid,age FROM user WHERE age=? AND user_name=?" + actualArgs := []interface{}{0, ""} + assert.Equal(t, sql, actualSql) + assert.Equal(t, args, actualArgs) + }) } func TestBuilderSqlIn(t *testing.T) { @@ -79,7 +101,7 @@ func TestBuilderSqlIn(t *testing.T) { } gtU := NewGt(u) in := builder.In("id", []string{"1", "2", "3"}) - sql, args, err := builder.Select(userFields...).From("user").Where(in).And(gtU).ToSQL() + sql, args, err := builder.Select(userFieldsWithRawStringQuote...).From("user").Where(in).And(gtU).ToSQL() fmt.Println(sql, args, err) actualSql := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE id IN (?,?,?) AND age>?" @@ -90,7 +112,7 @@ func TestBuilderSqlIn(t *testing.T) { func TestBuildSqlLike(t *testing.T) { like := builder.Like{"name", "wang"} - sql, args, err := builder.Select(userFields...).From("user").Where(like).ToSQL() + sql, args, err := builder.Select(userFieldsWithRawStringQuote...).From("user").Where(like).ToSQL() fmt.Println(sql, args, err) actualSql := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE name LIKE ?" diff --git a/tools/goctl/model/sql/example/makefile b/tools/goctl/model/sql/example/makefile index 7da64fe4..fa80267c 100644 --- a/tools/goctl/model/sql/example/makefile +++ b/tools/goctl/model/sql/example/makefile @@ -2,12 +2,12 @@ # generate model with cache from ddl fromDDLWithCache: - goctl template clean; - goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/cache/user" -cache; + goctl template clean + goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/cache" -cache fromDDLWithoutCache: goctl template clean; - goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/nocache/user"; + goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/nocache" # generate model with cache from data source @@ -17,5 +17,5 @@ datasource=127.0.0.1:3306 database=gozero fromDataSource: - goctl template clean; - goctl model mysql datasource -url="$(user):$(password)@tcp($(datasource))/$(database)" -table="*" -dir ./model/cache -c -style gozero; \ No newline at end of file + goctl template clean + goctl model mysql datasource -url="$(user):$(password)@tcp($(datasource))/$(database)" -table="*" -dir ./model/cache -c -style gozero diff --git a/tools/goctl/model/sql/gen/gen_test.go b/tools/goctl/model/sql/gen/gen_test.go index 348ad9cd..89e0e198 100644 --- a/tools/goctl/model/sql/gen/gen_test.go +++ b/tools/goctl/model/sql/gen/gen_test.go @@ -102,7 +102,7 @@ func TestFields(t *testing.T) { UpdateTime sql.NullTime `db:"update_time"` } var ( - studentFieldNames = builderx.FieldNames(&Student{}) + studentFieldNames = builderx.RawFieldNames(&Student{}) studentRows = strings.Join(studentFieldNames, ",") studentRowsExpectAutoSet = strings.Join(stringx.Remove(studentFieldNames, "`id`", "`create_time`", "`update_time`"), ",") studentRowsWithPlaceHolder = strings.Join(stringx.Remove(studentFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" diff --git a/tools/goctl/model/sql/template/vars.go b/tools/goctl/model/sql/template/vars.go index 254a6e07..f40bf325 100644 --- a/tools/goctl/model/sql/template/vars.go +++ b/tools/goctl/model/sql/template/vars.go @@ -4,7 +4,7 @@ import "fmt" var Vars = fmt.Sprintf(` var ( - {{.lowerStartCamelObject}}FieldNames = builderx.FieldNames(&{{.upperStartCamelObject}}{}) + {{.lowerStartCamelObject}}FieldNames = builderx.RawFieldNames(&{{.upperStartCamelObject}}{}) {{.lowerStartCamelObject}}Rows = strings.Join({{.lowerStartCamelObject}}FieldNames, ",") {{.lowerStartCamelObject}}RowsExpectAutoSet = strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}",{{end}} "%screate_time%s", "%supdate_time%s"), ",") {{.lowerStartCamelObject}}RowsWithPlaceHolder = strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, "{{.originalPrimaryKey}}", "%screate_time%s", "%supdate_time%s"), "=?,") + "=?" diff --git a/tools/goctl/model/sql/test/model/studentmodel.go b/tools/goctl/model/sql/test/model/studentmodel.go index b11ec0ed..01ee76f7 100755 --- a/tools/goctl/model/sql/test/model/studentmodel.go +++ b/tools/goctl/model/sql/test/model/studentmodel.go @@ -14,7 +14,7 @@ import ( ) var ( - studentFieldNames = builderx.FieldNames(&Student{}) + studentFieldNames = builderx.RawFieldNames(&Student{}) studentRows = strings.Join(studentFieldNames, ",") studentRowsExpectAutoSet = strings.Join(stringx.Remove(studentFieldNames, "`id`", "`create_time`", "`update_time`"), ",") studentRowsWithPlaceHolder = strings.Join(stringx.Remove(studentFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" diff --git a/tools/goctl/model/sql/test/model/usermodel.go b/tools/goctl/model/sql/test/model/usermodel.go index b6cf9a1f..bcef7843 100755 --- a/tools/goctl/model/sql/test/model/usermodel.go +++ b/tools/goctl/model/sql/test/model/usermodel.go @@ -15,8 +15,8 @@ import ( var ( userFieldNames = builderx.FieldNames(&User{}) userRows = strings.Join(userFieldNames, ",") - userRowsExpectAutoSet = strings.Join(stringx.Remove(userFieldNames, "`id`", "`create_time`", "`update_time`"), ",") - userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + userRowsExpectAutoSet = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), ",") + userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), "=?,") + "=?" ) type (