Fix issue 1205 (#1211)
* fix #1205 * move builder into stores * remove xrom * Remove unused code * Remove unused code * refactor builderx to builder Co-authored-by: anqiansong <anqiansong@bytedance.com>master
parent
c28e01fed3
commit
69a4d213a3
@ -0,0 +1,63 @@
|
|||||||
|
package builder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const dbTag = "db"
|
||||||
|
|
||||||
|
// RawFieldNames converts golang struct field into slice string.
|
||||||
|
func RawFieldNames(in interface{}, postgresSql ...bool) []string {
|
||||||
|
out := make([]string, 0)
|
||||||
|
v := reflect.ValueOf(in)
|
||||||
|
if v.Kind() == reflect.Ptr {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
var pg bool
|
||||||
|
if len(postgresSql) > 0 {
|
||||||
|
pg = postgresSql[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 != "" {
|
||||||
|
if pg {
|
||||||
|
out = append(out, tagv)
|
||||||
|
} else {
|
||||||
|
out = append(out, fmt.Sprintf("`%s`", tagv))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if pg {
|
||||||
|
out = append(out, fi.Name)
|
||||||
|
} else {
|
||||||
|
out = append(out, fmt.Sprintf("`%s`", fi.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostgreSqlJoin concatenates the given elements into a string.
|
||||||
|
func PostgreSqlJoin(elems []string) string {
|
||||||
|
b := new(strings.Builder)
|
||||||
|
for index, e := range elems {
|
||||||
|
b.WriteString(fmt.Sprintf("%s = $%d, ", e, index+2))
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.Len() == 0 {
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.String()[0 : b.Len()-2]
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package builder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockedUser struct {
|
||||||
|
ID string `db:"id" json:"id,omitempty"`
|
||||||
|
UserName string `db:"user_name" json:"userName,omitempty"`
|
||||||
|
Sex int `db:"sex" json:"sex,omitempty"`
|
||||||
|
UUID string `db:"uuid" uuid:"uuid,omitempty"`
|
||||||
|
Age int `db:"age" json:"age"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFieldNames(t *testing.T) {
|
||||||
|
t.Run("new", func(t *testing.T) {
|
||||||
|
var u mockedUser
|
||||||
|
out := RawFieldNames(&u)
|
||||||
|
expected := []string{"`id`", "`user_name`", "`sex`", "`uuid`", "`age`"}
|
||||||
|
assert.Equal(t, expected, out)
|
||||||
|
})
|
||||||
|
}
|
@ -1,136 +1,20 @@
|
|||||||
package builderx
|
package builderx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"github.com/tal-tech/go-zero/core/stores/builder"
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-xorm/builder"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const dbTag = "db"
|
// Deprecated: Use github.com/tal-tech/go-zero/core/stores/builder.RawFieldNames instead.
|
||||||
|
|
||||||
// NewEq wraps builder.Eq.
|
|
||||||
func NewEq(in interface{}) builder.Eq {
|
|
||||||
return builder.Eq(ToMap(in))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGt wraps builder.Gt.
|
|
||||||
func NewGt(in interface{}) builder.Gt {
|
|
||||||
return builder.Gt(ToMap(in))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToMap converts interface into map.
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// FieldNames returns field names from given in.
|
|
||||||
// deprecated: use RawFieldNames instead automatically while model generating after goctl version v1.1.0
|
|
||||||
func FieldNames(in interface{}) []string {
|
func FieldNames(in interface{}) []string {
|
||||||
out := make([]string, 0)
|
return builder.RawFieldNames(in)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RawFieldNames converts golang struct field into slice string.
|
// Deprecated: Use github.com/tal-tech/go-zero/core/stores/builder.RawFieldNames instead.
|
||||||
func RawFieldNames(in interface{}, postgresSql ...bool) []string {
|
func RawFieldNames(in interface{}, postgresSql ...bool) []string {
|
||||||
out := make([]string, 0)
|
return builder.RawFieldNames(in, postgresSql...)
|
||||||
v := reflect.ValueOf(in)
|
|
||||||
if v.Kind() == reflect.Ptr {
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
var pg bool
|
|
||||||
if len(postgresSql) > 0 {
|
|
||||||
pg = postgresSql[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 != "" {
|
|
||||||
if pg {
|
|
||||||
out = append(out, tagv)
|
|
||||||
} else {
|
|
||||||
out = append(out, fmt.Sprintf("`%s`", tagv))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if pg {
|
|
||||||
out = append(out, fi.Name)
|
|
||||||
} else {
|
|
||||||
out = append(out, fmt.Sprintf("`%s`", fi.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostgreSqlJoin concatenates the given elements into a string.
|
// Deprecated: Use github.com/tal-tech/go-zero/core/stores/builderx.PostgreSqlJoin instead.
|
||||||
func PostgreSqlJoin(elems []string) string {
|
func PostgreSqlJoin(elems []string) string {
|
||||||
b := new(strings.Builder)
|
return builder.PostgreSqlJoin(elems)
|
||||||
for index, e := range elems {
|
|
||||||
b.WriteString(fmt.Sprintf("%s = $%d, ", e, index+2))
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.Len() == 0 {
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.String()[0 : b.Len()-2]
|
|
||||||
}
|
}
|
||||||
|
@ -1,125 +0,0 @@
|
|||||||
package builderx
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/go-xorm/builder"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mockedUser 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 (
|
|
||||||
userFieldsWithRawStringQuote = RawFieldNames(mockedUser{})
|
|
||||||
userFieldsWithoutRawStringQuote = FieldNames(mockedUser{})
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFieldNames(t *testing.T) {
|
|
||||||
t.Run("old", func(t *testing.T) {
|
|
||||||
var u mockedUser
|
|
||||||
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 mockedUser
|
|
||||||
out := RawFieldNames(&u)
|
|
||||||
expected := []string{"`id`", "`user_name`", "`sex`", "`uuid`", "`age`"}
|
|
||||||
assert.Equal(t, expected, out)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewEq(t *testing.T) {
|
|
||||||
u := &mockedUser{
|
|
||||||
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 := &mockedUser{
|
|
||||||
ID: "123123",
|
|
||||||
}
|
|
||||||
fields := RawFieldNames(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) {
|
|
||||||
eq := builder.Eq{}
|
|
||||||
eq["age"] = 0
|
|
||||||
eq["user_name"] = ""
|
|
||||||
|
|
||||||
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)
|
|
||||||
})
|
|
||||||
|
|
||||||
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) {
|
|
||||||
u := &mockedUser{
|
|
||||||
Age: 18,
|
|
||||||
}
|
|
||||||
gtU := NewGt(u)
|
|
||||||
in := builder.In("id", []string{"1", "2", "3"})
|
|
||||||
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>?"
|
|
||||||
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(userFieldsWithRawStringQuote...).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)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestJoin(t *testing.T) {
|
|
||||||
ret := PostgreSqlJoin([]string{"name", "age"})
|
|
||||||
assert.Equal(t, "name = $2, age = $3", ret)
|
|
||||||
}
|
|
Loading…
Reference in New Issue