mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-11 00:40:00 +08:00
reactor sql generation
This commit is contained in:
97
tools/goctl/model/sql/builderx/builder.go
Normal file
97
tools/goctl/model/sql/builderx/builder.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package builderx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-xorm/builder"
|
||||
)
|
||||
|
||||
const dbTag = "db"
|
||||
|
||||
func NewEq(in interface{}) builder.Eq {
|
||||
return builder.Eq(ToMap(in))
|
||||
}
|
||||
|
||||
func NewGt(in interface{}) builder.Gt {
|
||||
return builder.Gt(ToMap(in))
|
||||
}
|
||||
|
||||
func ToMap(in interface{}) map[string]interface{} {
|
||||
out := make(map[string]interface{})
|
||||
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 != "" {
|
||||
// set key of map to value in struct field
|
||||
val := v.Field(i)
|
||||
zero := reflect.Zero(val.Type()).Interface()
|
||||
current := val.Interface()
|
||||
|
||||
if reflect.DeepEqual(current, zero) {
|
||||
continue
|
||||
}
|
||||
out[tagv] = current
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func FieldNames(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, tagv)
|
||||
} else {
|
||||
out = append(out, fi.Name)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
func FieldNamesAlias(in interface{}, alias string) []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)
|
||||
tagName := ""
|
||||
if tagv := fi.Tag.Get(dbTag); tagv != "" {
|
||||
tagName = tagv
|
||||
} else {
|
||||
tagName = fi.Name
|
||||
}
|
||||
if len(alias) > 0 {
|
||||
tagName = alias + "." + tagName
|
||||
}
|
||||
out = append(out, tagName)
|
||||
}
|
||||
return out
|
||||
}
|
||||
101
tools/goctl/model/sql/builderx/builder_test.go
Normal file
101
tools/goctl/model/sql/builderx/builder_test.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package builderx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/go-xorm/builder"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type (
|
||||
User struct {
|
||||
// 自增id
|
||||
Id string `db:"id" json:"id,omitempty"`
|
||||
// 姓名
|
||||
UserName string `db:"user_name" json:"userName,omitempty"`
|
||||
// 1男,2女
|
||||
Sex int `db:"sex" json:"sex,omitempty"`
|
||||
|
||||
Uuid string `db:"uuid" uuid:"uuid,omitempty"`
|
||||
|
||||
Age int `db:"age" json:"age"`
|
||||
}
|
||||
)
|
||||
|
||||
var userFields = FieldNames(User{})
|
||||
|
||||
func TestFieldNames(t *testing.T) {
|
||||
var u User
|
||||
out := FieldNames(&u)
|
||||
fmt.Println(out)
|
||||
actual := []string{"id", "user_name", "sex", "uuid", "age"}
|
||||
assert.Equal(t, out, actual)
|
||||
}
|
||||
|
||||
func TestNewEq(t *testing.T) {
|
||||
u := &User{
|
||||
Id: "123456",
|
||||
UserName: "wahaha",
|
||||
}
|
||||
out := NewEq(u)
|
||||
fmt.Println(out)
|
||||
actual := builder.Eq{"id": "123456", "user_name": "wahaha"}
|
||||
assert.Equal(t, out, actual)
|
||||
}
|
||||
|
||||
// @see https://github.com/go-xorm/builder
|
||||
func TestBuilderSql(t *testing.T) {
|
||||
u := &User{
|
||||
Id: "123123",
|
||||
}
|
||||
fields := FieldNames(u)
|
||||
eq := NewEq(u)
|
||||
sql, args, err := builder.Select(fields...).From("user").Where(eq).ToSQL()
|
||||
fmt.Println(sql, args, err)
|
||||
|
||||
actualSql := "SELECT id,user_name,sex,uuid,age FROM user WHERE id=?"
|
||||
actualArgs := []interface{}{"123123"}
|
||||
assert.Equal(t, sql, actualSql)
|
||||
assert.Equal(t, args, actualArgs)
|
||||
}
|
||||
|
||||
func TestBuildSqlDefaultValue(t *testing.T) {
|
||||
var eq = builder.Eq{}
|
||||
eq["age"] = 0
|
||||
eq["user_name"] = ""
|
||||
|
||||
sql, args, err := builder.Select(userFields...).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) {
|
||||
u := &User{
|
||||
Age: 18,
|
||||
}
|
||||
gtU := NewGt(u)
|
||||
in := builder.In("id", []string{"1", "2", "3"})
|
||||
sql, args, err := builder.Select(userFields...).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>?"
|
||||
actualArgs := []interface{}{"1", "2", "3", 18}
|
||||
assert.Equal(t, sql, actualSql)
|
||||
assert.Equal(t, args, actualArgs)
|
||||
}
|
||||
|
||||
func TestBuildSqlLike(t *testing.T) {
|
||||
like := builder.Like{"name", "wang"}
|
||||
sql, args, err := builder.Select(userFields...).From("user").Where(like).ToSQL()
|
||||
fmt.Println(sql, args, err)
|
||||
|
||||
actualSql := "SELECT id,user_name,sex,uuid,age FROM user WHERE name LIKE ?"
|
||||
actualArgs := []interface{}{"%wang%"}
|
||||
assert.Equal(t, sql, actualSql)
|
||||
assert.Equal(t, args, actualArgs)
|
||||
}
|
||||
@@ -13,7 +13,9 @@ func genDelete(table Table, withCache bool) (string, error) {
|
||||
keySet := collection.NewSet()
|
||||
keyVariableSet := collection.NewSet()
|
||||
for fieldName, key := range table.CacheKey {
|
||||
keySet.AddStr(key.KeyExpression)
|
||||
if fieldName == table.PrimaryKey.Name.Source() {
|
||||
keySet.AddStr(key.KeyExpression)
|
||||
}
|
||||
if fieldName != table.PrimaryKey.Name.Source() {
|
||||
keySet.AddStr(key.DataKeyExpression)
|
||||
}
|
||||
@@ -33,7 +35,7 @@ func genDelete(table Table, withCache bool) (string, error) {
|
||||
"upperStartCamelObject": camel,
|
||||
"withCache": withCache,
|
||||
"containsIndexCache": containsIndexCache,
|
||||
"lowerStartCamelPrimaryKey": stringx.From(camel).LowerStart(),
|
||||
"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.Snake2Camel()).LowerStart(),
|
||||
"dataType": table.PrimaryKey.DataType,
|
||||
"keys": strings.Join(keySet.KeysStr(), "\n"),
|
||||
"originalPrimaryKey": table.PrimaryKey.Name.Source(),
|
||||
|
||||
@@ -21,13 +21,18 @@ func genFields(fields []parser.Field) (string, error) {
|
||||
}
|
||||
|
||||
func genField(field parser.Field) (string, error) {
|
||||
tag, err := genTag(field.Name.Source())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
output, err := templatex.With("types").
|
||||
Parse(template.Field).
|
||||
Execute(map[string]string{
|
||||
"name": field.Name.Snake2Camel(),
|
||||
"type": field.DataType,
|
||||
"tag": field.Name.Source(),
|
||||
"comment": field.Comment,
|
||||
Execute(map[string]interface{}{
|
||||
"name": field.Name.Snake2Camel(),
|
||||
"type": field.DataType,
|
||||
"tag": tag,
|
||||
"hasComment": field.Comment != "",
|
||||
"comment": field.Comment,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
@@ -14,7 +14,7 @@ func genFineOneByField(table Table, withCache bool) (string, error) {
|
||||
var list []string
|
||||
camelTableName := table.Name.Snake2Camel()
|
||||
for _, field := range table.Fields {
|
||||
if field.IsPrimaryKey {
|
||||
if field.IsPrimaryKey || !field.IsKey {
|
||||
continue
|
||||
}
|
||||
camelFieldName := field.Name.Snake2Camel()
|
||||
@@ -25,7 +25,7 @@ func genFineOneByField(table Table, withCache bool) (string, error) {
|
||||
"withCache": withCache,
|
||||
"cacheKey": table.CacheKey[field.Name.Source()].KeyExpression,
|
||||
"cacheKeyVariable": table.CacheKey[field.Name.Source()].Variable,
|
||||
"primaryKeyLeft": table.CacheKey[table.Name.Source()].Left,
|
||||
"primaryKeyLeft": table.CacheKey[table.PrimaryKey.Name.Source()].Left,
|
||||
"lowerStartCamelObject": stringx.From(camelTableName).LowerStart(),
|
||||
"lowerStartCamelField": stringx.From(camelFieldName).LowerStart(),
|
||||
"upperStartCamelPrimaryKey": table.PrimaryKey.Name.Snake2Camel(),
|
||||
|
||||
@@ -104,7 +104,10 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
importsCode := genImports()
|
||||
importsCode, err := genImports(withCache)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var table Table
|
||||
table.Table = in
|
||||
table.CacheKey = m
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
sqltemplate "github.com/tal-tech/go-zero/tools/goctl/model/sql/template"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/template"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util/templatex"
|
||||
)
|
||||
|
||||
func genImports() string {
|
||||
return sqltemplate.Imports
|
||||
func genImports(withCache bool) (string, error) {
|
||||
output, err := templatex.With("import").
|
||||
Parse(template.Imports).
|
||||
Execute(map[string]interface{}{
|
||||
"withCache": withCache,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return output.String(), nil
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func genCacheKeys(table parser.Table) (map[string]Key, error) {
|
||||
}
|
||||
camelFieldName := field.Name.Snake2Camel()
|
||||
lowerStartCamelFieldName := stringx.From(camelFieldName).LowerStart()
|
||||
left := fmt.Sprintf("cache%s%sPrefix", camelTableName, camelFieldName)
|
||||
left := fmt.Sprintf("cache%s%sPrefix", lowerStartCamelTableName, camelFieldName)
|
||||
right := fmt.Sprintf("cache#%s#%s#", lowerStartCamelTableName, lowerStartCamelFieldName)
|
||||
variable := fmt.Sprintf("%s%sKey", lowerStartCamelTableName, camelFieldName)
|
||||
m[field.Name.Source()] = Key{
|
||||
@@ -42,9 +42,9 @@ func genCacheKeys(table parser.Table) (map[string]Key, error) {
|
||||
Left: left,
|
||||
Right: right,
|
||||
Variable: variable,
|
||||
KeyExpression: fmt.Sprintf(`%s := fmt.Sprintf("cache#user#id#%s", %s)`, variable, "%s", lowerStartCamelFieldName),
|
||||
DataKeyExpression: fmt.Sprintf(`%s := fmt.Sprintf("cache#user#id#%s", data.%s)`, variable, "%s", lowerStartCamelFieldName),
|
||||
RespKeyExpression: fmt.Sprintf(`%s := fmt.Sprintf("cache#user#id#%s", resp.%s)`, variable, "%s", lowerStartCamelFieldName),
|
||||
KeyExpression: fmt.Sprintf(`%s := fmt.Sprintf("cache#%s#%s#%s", %s)`, variable, lowerStartCamelTableName, lowerStartCamelFieldName, "%v", lowerStartCamelFieldName),
|
||||
DataKeyExpression: fmt.Sprintf(`%s := fmt.Sprintf("cache#%s#%s#%s", data.%s)`, variable, lowerStartCamelTableName, lowerStartCamelFieldName, "%v", camelFieldName),
|
||||
RespKeyExpression: fmt.Sprintf(`%s := fmt.Sprintf("cache#%s#%s#%s", resp.%s)`, variable, lowerStartCamelTableName, lowerStartCamelFieldName, "%v", camelFieldName),
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
|
||||
@@ -8,6 +8,14 @@ import (
|
||||
"github.com/xwb1989/sqlparser"
|
||||
)
|
||||
|
||||
const (
|
||||
none = iota
|
||||
primary
|
||||
unique
|
||||
normal
|
||||
spatial
|
||||
)
|
||||
|
||||
type (
|
||||
Table struct {
|
||||
Name stringx.String
|
||||
@@ -26,6 +34,7 @@ type (
|
||||
IsPrimaryKey bool
|
||||
Comment string
|
||||
}
|
||||
KeyType int
|
||||
)
|
||||
|
||||
func Parse(ddl string) (*Table, error) {
|
||||
@@ -50,6 +59,7 @@ func Parse(ddl string) (*Table, error) {
|
||||
columns := tableSpec.Columns
|
||||
indexes := tableSpec.Indexes
|
||||
|
||||
keyMap := make(map[string]KeyType)
|
||||
for _, index := range indexes {
|
||||
info := index.Info
|
||||
if info == nil {
|
||||
@@ -59,13 +69,33 @@ func Parse(ddl string) (*Table, error) {
|
||||
if len(index.Columns) > 1 {
|
||||
return nil, errPrimaryKey
|
||||
}
|
||||
break
|
||||
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
|
||||
@@ -83,17 +113,18 @@ func Parse(ddl string) (*Table, error) {
|
||||
field.DataBaseType = column.Type.Type
|
||||
field.DataType = dataType
|
||||
field.Comment = comment
|
||||
// see line 1194 https://github.com/xwb1989/sqlparser/blob/master/ast.go
|
||||
field.IsKey = column.Type.KeyOpt != 0
|
||||
field.IsPrimaryKey = column.Type.KeyOpt == 1
|
||||
fields = append(fields, field)
|
||||
// see line 1195 https://github.com/xwb1989/sqlparser/blob/master/ast.go
|
||||
if column.Type.KeyOpt == 1 {
|
||||
primaryKey.Field = field
|
||||
if column.Type.Autoincrement {
|
||||
primaryKey.AutoIncrement = true
|
||||
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),
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
package template
|
||||
|
||||
var Field = `{{.name}} {{.type}} {{.tag}} {{.comment}}`
|
||||
var Field = `{{.name}} {{.type}} {{.tag}} {{if .hasComment}}// {{.comment}}{{end}}`
|
||||
|
||||
@@ -55,5 +55,15 @@ func (m *{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}({{.in}}) (*{{
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}{{else}}var resp {{.upperStartCamelObject}}
|
||||
query := ` + "`" + `select ` + "`" + ` + {{.lowerStartCamelObject}}Rows + ` + "`" + ` from ` + "` + " + `m.table ` + " + `" + ` where {{.originalField}} limit 1` + "`" + `
|
||||
err := m.QueryRowNoCache(&resp, query, {{.lowerStartCamelField}})
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}{{end}}
|
||||
`
|
||||
|
||||
@@ -2,13 +2,15 @@ package template
|
||||
|
||||
var Imports = `
|
||||
import (
|
||||
"database/sql"
|
||||
"strings"
|
||||
"database/sql"{{if .withCache}}
|
||||
"fmt"
|
||||
{{end}}"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tal-tech/go-zero/core/stores/cache"
|
||||
"github.com/tal-tech/go-zero/core/stores/sqlc"
|
||||
"github.com/tal-tech/go-zero/core/stores/sqlx"
|
||||
"github.com/tal-tech/go-zero/core/stringx"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
|
||||
)
|
||||
`
|
||||
|
||||
@@ -4,7 +4,7 @@ var Vars = `
|
||||
var (
|
||||
{{.lowerStartCamelObject}}FieldNames = builderx.FieldNames(&{{.upperStartCamelObject}}{})
|
||||
{{.lowerStartCamelObject}}Rows = strings.Join({{.lowerStartCamelObject}}FieldNames, ",")
|
||||
{{.lowerStartCamelObject}}RowsExpectAutoSet = strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{.if autoIncrement}}"{{.originalPrimaryKey}}",{{end}} "create_time", "update_time"), ",")
|
||||
{{.lowerStartCamelObject}}RowsExpectAutoSet = strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}",{{end}} "create_time", "update_time"), ",")
|
||||
{{.lowerStartCamelObject}}RowsWithPlaceHolder = strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, "{{.originalPrimaryKey}}", "create_time", "update_time"), "=?,") + "=?"
|
||||
|
||||
{{.cacheKeys}}
|
||||
|
||||
149
tools/goctl/model/sql/test/modelwithcache/testmodel.go
Normal file
149
tools/goctl/model/sql/test/modelwithcache/testmodel.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tal-tech/go-zero/core/stores/cache"
|
||||
"github.com/tal-tech/go-zero/core/stores/sqlc"
|
||||
"github.com/tal-tech/go-zero/core/stores/sqlx"
|
||||
"github.com/tal-tech/go-zero/core/stringx"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
|
||||
)
|
||||
|
||||
var (
|
||||
userCamelFieldNames = builderx.FieldNames(&UserCamel{})
|
||||
userCamelRows = strings.Join(userCamelFieldNames, ",")
|
||||
userCamelRowsExpectAutoSet = strings.Join(stringx.Remove(userCamelFieldNames, "create_time", "update_time"), ",")
|
||||
userCamelRowsWithPlaceHolder = strings.Join(stringx.Remove(userCamelFieldNames, "id", "create_time", "update_time"), "=?,") + "=?"
|
||||
|
||||
cacheuserCamelIdPrefix = "cache#userCamel#id#"
|
||||
cacheuserCamelNamePrefix = "cache#userCamel#name#"
|
||||
cacheuserCamelMobilePrefix = "cache#userCamel#mobile#"
|
||||
|
||||
ErrNotFound = sqlx.ErrNotFound
|
||||
)
|
||||
|
||||
type (
|
||||
UserCamelModel struct {
|
||||
sqlc.CachedConn
|
||||
table string
|
||||
}
|
||||
|
||||
UserCamel struct {
|
||||
Id int64 `db:"id"`
|
||||
Name string `db:"name"` // 用户名称
|
||||
Password string `db:"password"` // 用户密码
|
||||
Mobile string `db:"mobile"` // 手机号
|
||||
Gender string `db:"gender"` // 男|女|未公开
|
||||
Nickname string `db:"nickname"` // 用户昵称
|
||||
CreateTime time.Time `db:"createTime"`
|
||||
UpdateTime time.Time `db:"updateTime"`
|
||||
}
|
||||
)
|
||||
|
||||
func NewUserCamelModel(conn sqlx.SqlConn, c cache.CacheConf, table string) *UserCamelModel {
|
||||
return &UserCamelModel{
|
||||
CachedConn: sqlc.NewConn(conn, c),
|
||||
table: table,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *UserCamelModel) Insert(data UserCamel) error {
|
||||
query := `insert into ` + m.table + `(` + userCamelRowsExpectAutoSet + `) value (?, ?, ?, ?, ?, ?)`
|
||||
_, err := m.ExecNoCache(query, data.Id, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *UserCamelModel) FindOne(id int64) (*UserCamel, error) {
|
||||
userCamelIdKey := fmt.Sprintf("cache#userCamel#id#%v", id)
|
||||
var resp UserCamel
|
||||
err := m.QueryRow(&resp, userCamelIdKey, func(conn sqlx.SqlConn, v interface{}) error {
|
||||
query := `select ` + userCamelRows + ` from ` + m.table + ` where id = ? limit 1`
|
||||
return conn.QueryRow(v, query, id)
|
||||
})
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *UserCamelModel) FindOneByName(name string) (*UserCamel, error) {
|
||||
userCamelNameKey := fmt.Sprintf("cache#userCamel#name#%v", name)
|
||||
var resp UserCamel
|
||||
err := m.QueryRowIndex(&resp, userCamelNameKey, func(primary interface{}) string {
|
||||
return fmt.Sprintf("%s%v", cacheuserCamelIdPrefix, primary)
|
||||
}, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||
query := `select ` + userCamelRows + ` from ` + m.table + ` where name = ? limit 1`
|
||||
if err := conn.QueryRow(&resp, query, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Id, nil
|
||||
}, func(conn sqlx.SqlConn, v, primary interface{}) error {
|
||||
query := `select ` + userCamelRows + ` from ` + m.table + ` where id = ? limit 1`
|
||||
return conn.QueryRow(v, query, primary)
|
||||
})
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *UserCamelModel) FindOneByMobile(mobile string) (*UserCamel, error) {
|
||||
userCamelMobileKey := fmt.Sprintf("cache#userCamel#mobile#%v", mobile)
|
||||
var resp UserCamel
|
||||
err := m.QueryRowIndex(&resp, userCamelMobileKey, func(primary interface{}) string {
|
||||
return fmt.Sprintf("%s%v", cacheuserCamelIdPrefix, primary)
|
||||
}, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||
query := `select ` + userCamelRows + ` from ` + m.table + ` where mobile = ? limit 1`
|
||||
if err := conn.QueryRow(&resp, query, mobile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Id, nil
|
||||
}, func(conn sqlx.SqlConn, v, primary interface{}) error {
|
||||
query := `select ` + userCamelRows + ` from ` + m.table + ` where id = ? limit 1`
|
||||
return conn.QueryRow(v, query, primary)
|
||||
})
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *UserCamelModel) Update(data UserCamel) error {
|
||||
userCamelIdKey := fmt.Sprintf("cache#userCamel#id#%v", data.Id)
|
||||
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := `update ` + m.table + ` set ` + userCamelRowsWithPlaceHolder + ` where id = ?`
|
||||
return conn.Exec(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Id)
|
||||
}, userCamelIdKey)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *UserCamelModel) Delete(id int64) error {
|
||||
data, err := m.FindOne(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userCamelIdKey := fmt.Sprintf("cache#userCamel#id#%v", id)
|
||||
userCamelNameKey := fmt.Sprintf("cache#userCamel#name#%v", data.Name)
|
||||
userCamelMobileKey := fmt.Sprintf("cache#userCamel#mobile#%v", data.Mobile)
|
||||
_, err = m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := `delete from ` + m.table + ` where id = ?`
|
||||
return conn.Exec(query, id)
|
||||
}, userCamelIdKey, userCamelNameKey, userCamelMobileKey)
|
||||
return err
|
||||
}
|
||||
20
tools/goctl/model/sql/test/sql_test.go
Normal file
20
tools/goctl/model/sql/test/sql_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/gen"
|
||||
)
|
||||
|
||||
func TestGenSqlWithCache(t *testing.T) {
|
||||
generator := gen.NewDefaultGenerator("./test.sql", "./modelwithcache")
|
||||
err := generator.Start(true)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestGenSqlWithoutCache(t *testing.T) {
|
||||
generator := gen.NewDefaultGenerator("./test.sql", "./modelwithoutcache")
|
||||
err := generator.Start(false)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
30
tools/goctl/model/sql/test/test.sql
Normal file
30
tools/goctl/model/sql/test/test.sql
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
-- user_snake
|
||||
CREATE TABLE `user_snake` (
|
||||
`id` bigint(10) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',
|
||||
`password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
|
||||
`mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',
|
||||
`gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',
|
||||
`nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',
|
||||
`create_time` timestamp NULL DEFAULT NULL,
|
||||
`update_time` timestamp NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `name_index` (`name`),
|
||||
KEY `mobile_index` (`mobile`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
-- userCamel (disable AUTO_INCREMENT)
|
||||
CREATE TABLE `userCamel` (
|
||||
`id` bigint(10) NOT NULL,
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',
|
||||
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
|
||||
`mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',
|
||||
`gender` char(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',
|
||||
`nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',
|
||||
`createTime` timestamp NULL DEFAULT NULL,
|
||||
`updateTime` timestamp NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `nameIndex` (`name`),
|
||||
KEY `mobile_index` (`mobile`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
@@ -87,7 +87,7 @@ func (s String) LowerStart() string {
|
||||
if !unicode.IsUpper(r) && !unicode.IsLower(r) {
|
||||
return s.source
|
||||
}
|
||||
return string(r) + s.source[1:]
|
||||
return string(unicode.ToLower(r)) + s.source[1:]
|
||||
}
|
||||
|
||||
// it will not ignore spaces
|
||||
|
||||
Reference in New Issue
Block a user