This commit is contained in:
xing 2022-11-06 12:04:41 +08:00
parent f0dae59d18
commit e453dd996e
4 changed files with 198 additions and 15 deletions

View File

@ -222,7 +222,7 @@ func SliceReduce[T, R any](arr []T, fn func(T, R) R, r R) R {
} }
func SliceReverse[T any](arr []T) []T { func SliceReverse[T any](arr []T) []T {
var r []T var r = make([]T, 0, len(arr))
for i := len(arr); i > 0; i-- { for i := len(arr); i > 0; i-- {
r = append(r, arr[i-1]) r = append(r, arr[i-1])
} }
@ -308,3 +308,17 @@ func Max[T IntNumber | ~float64 | ~float32](a ...T) T {
} }
return max return max
} }
func SliceChunk[T any](arr []T, size int) [][]T {
var r [][]T
i := 0
for {
if len(arr) <= size+i {
r = append(r, arr[i:])
break
}
r = append(r, arr[i:i+size])
i += size
}
return r
}

View File

@ -708,3 +708,39 @@ func TestMax(t *testing.T) {
}) })
} }
} }
func TestSliceChunk(t *testing.T) {
type args struct {
arr []int
size int
}
tests := []struct {
name string
args args
want [][]int
}{
{
name: "t1",
args: args{
arr: RangeSlice(1, 7, 1),
size: 2,
},
want: [][]int{{1, 2}, {3, 4}, {5, 6}, {7}},
},
{
name: "t2",
args: args{
arr: RangeSlice(1, 8, 1),
size: 2,
},
want: [][]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := SliceChunk(tt.args.arr, tt.args.size); !reflect.DeepEqual(got, tt.want) {
t.Errorf("SliceChunk() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -73,6 +73,23 @@ func (w SqlBuilder) parseType(ss []string, args *[]any) error {
return nil return nil
} }
// ParseWhere 解析为where条件支持3种风格,具体用法参照query_test中的 Find 的测试方法
//
// 1. 2个为一组 {{"field1","value1"},{"field2","value2"}} => where field1='value1' and field2='value2'
//
// 2. 3个或4个为一组 {{"field","operator","value"[,"int|float"]}} => where field operator 'string'|int|float
//
// {{"a",">","1","int"}} => where 'a'> 1
//
// {{ "a",">","1"}} => where 'a'>'1'
//
// 另外如果是操作符为in的话为 {{"field","in",""}} => where field in (?,..) in的条件传给 in参数
//
// 3. 5的倍数为一组{{"and|or","field","operator","value","int|float"}}会忽然掉第一组的and|or
//
// {{"and","field","=","value1","","and","field","=","value2",""}} => where (field = 'value1' and field = 'value2')
//
// {{"and","field","=","num1","int","or","field","=","num2","int"}} => where (field = num1 or field = num2')
func (w SqlBuilder) ParseWhere(in *[][]any) (string, []any, error) { func (w SqlBuilder) ParseWhere(in *[][]any) (string, []any, error) {
var s strings.Builder var s strings.Builder
args := make([]any, 0, len(w)) args := make([]any, 0, len(w))

View File

@ -29,17 +29,112 @@ func TestFind(t *testing.T) {
limit int limit int
in [][]any in [][]any
} }
type posts struct {
wp.Posts
N int `db:"n"`
}
tests := []struct { tests := []struct {
name string name string
args args args args
wantR []wp.Posts wantR []posts
wantErr bool wantErr bool
}{ }{
{}, {
name: "in,orderBy",
args: args{
where: SqlBuilder{{
"post_status", "publish",
}, {"ID", "in", ""}},
fields: "*",
group: "",
order: SqlBuilder{{"ID", "desc"}},
join: nil,
having: nil,
limit: 0,
in: [][]any{{1, 2, 3, 4}},
},
wantR: func() []posts {
r, err := Select[posts]("select * from " + posts{}.Table() + " where post_status='publish' and ID in (1,2,3,4) order by ID desc")
if err != nil {
panic(err)
}
return r
}(),
wantErr: false,
},
{
name: "or",
args: args{
where: SqlBuilder{{
"and", "ID", "=", "1", "int",
}, {"or", "ID", "=", "2", "int"}},
fields: "*",
group: "",
order: nil,
join: nil,
having: nil,
limit: 0,
in: nil,
},
wantR: func() []posts {
r, err := Select[posts]("select * from " + posts{}.Table() + " where (ID=1 or ID=2)")
if err != nil {
panic(err)
}
return r
}(),
},
{
name: "group,having",
args: args{
where: SqlBuilder{
{"ID", "<", "1000", "int"},
},
fields: "post_status,count(*) n",
group: "post_status",
order: nil,
join: nil,
having: SqlBuilder{
{"n", ">", "1"},
},
limit: 0,
in: nil,
},
wantR: func() []posts {
r, err := Select[posts]("select post_status,count(*) n from " + wp.Posts{}.Table() + " where ID<1000 group by post_status having n>1")
if err != nil {
panic(err)
}
return r
}(),
},
{
name: "or、多个in",
args: args{
where: SqlBuilder{
{"and", "ID", "in", "", "", "or", "ID", "in", "", ""},
{"or", "post_status", "=", "publish", "", "and", "post_status", "=", "closed", ""},
},
fields: "*",
group: "",
order: nil,
join: nil,
having: nil,
limit: 0,
in: [][]any{{1, 2, 3}, {4, 5, 6}},
},
wantR: func() []posts {
r, err := Select[posts]("select * from " + posts{}.Table() + " where (ID in (1,2,3) or ID in (4,5,6)) or (post_status='publish' and post_status='closed')")
if err != nil {
panic(err)
}
return r
}(),
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
gotR, err := Find[wp.Posts](tt.args.where, tt.args.fields, tt.args.group, tt.args.order, tt.args.join, tt.args.having, tt.args.limit, tt.args.in...) gotR, err := Find[posts](tt.args.where, tt.args.fields, tt.args.group, tt.args.order, tt.args.join, tt.args.having, tt.args.limit, tt.args.in...)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("Find() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("Find() error = %v, wantErr %v", err, tt.wantErr)
return return
@ -55,10 +150,7 @@ func TestFindOneById(t *testing.T) {
type args struct { type args struct {
id int id int
} }
r, err := Get[wp.Posts]("select * from "+wp.Posts{}.Table()+" where ID=?", 1)
if err != nil {
panic(err)
}
tests := []struct { tests := []struct {
name string name string
args args args args
@ -70,7 +162,13 @@ func TestFindOneById(t *testing.T) {
args: args{ args: args{
1, 1,
}, },
want: r, want: func() wp.Posts {
r, err := Get[wp.Posts]("select * from "+wp.Posts{}.Table()+" where ID=?", 1)
if err != nil {
panic(err)
}
return r
}(),
wantErr: false, wantErr: false,
}, },
} }
@ -95,10 +193,6 @@ func TestFirstOne(t *testing.T) {
order SqlBuilder order SqlBuilder
in [][]any in [][]any
} }
r, err := Get[wp.Posts]("select * from " + wp.Posts{}.Table() + " where post_status='publish' order by ID desc")
if err != nil {
panic(err)
}
tests := []struct { tests := []struct {
name string name string
args args args args
@ -114,7 +208,13 @@ func TestFirstOne(t *testing.T) {
in: nil, in: nil,
}, },
wantErr: false, wantErr: false,
want: r, want: func() wp.Posts {
r, err := Get[wp.Posts]("select * from " + wp.Posts{}.Table() + " where post_status='publish' order by ID desc limit 1")
if err != nil {
panic(err)
}
return r
}(),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -170,7 +270,23 @@ func TestLastOne(t *testing.T) {
want wp.Posts want wp.Posts
wantErr bool wantErr bool
}{ }{
{}, {
name: "t1",
args: args{
where: SqlBuilder{{
"post_status", "publish",
}},
fields: "*",
in: nil,
},
want: func() wp.Posts {
r, err := Get[wp.Posts]("select * from " + wp.Posts{}.Table() + " where post_status='publish' order by " + wp.Posts{}.PrimaryKey() + " desc limit 1")
if err != nil {
panic(err)
}
return r
}(),
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {