Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

支持where 条件中的key 根据value判断是否op为in #109

Merged
merged 2 commits into from
Feb 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ builder isn't an ORM, in fact one of the most important reasons we create Gendry

```go
where := map[string]interface{}{
"city in": []string{"beijing", "shanghai"},
"city": []string{"beijing", "shanghai"},
// The in operator can be omitted by default,
// which is equivalent to:
// "city in": []string{"beijing", "shanghai"},
"score": 5,
"age >": 35,
"address": builder.IsNotNull,
Expand All @@ -81,12 +84,27 @@ cond, values, err := builder.BuildSelect(table, where, selectFields)

rows, err := db.Query(cond, values...)
```

In the `where` param, automatically add 'in' operator by value type(reflect.Slice).

```go
where := map[string]interface{}{
"city": []string{"beijing", "shanghai"},
}
```
the same as
```go
where := map[string]interface{}{
"city in": []string{"beijing", "shanghai"},
}
```

And, the library provide a useful API for executing aggregate queries like count, sum, max, min, avg

```go
where := map[string]interface{}{
"score > ": 100,
"city in": []interface{}{"Beijing", "Shijiazhuang", }
"city": []interface{}{"Beijing", "Shijiazhuang", }
}
// AggregateSum, AggregateMax, AggregateMin, AggregateCount, AggregateAvg are supported
result, err := AggregateQuery(ctx, db, "tableName", where, AggregateSum("age"))
Expand Down
9 changes: 6 additions & 3 deletions builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func resolveHaving(having interface{}) (map[string]interface{}, error) {
}
copiedMap := make(map[string]interface{})
for key, val := range havingMap {
_, operator, err := splitKey(key)
_, operator, err := splitKey(key, val)
if nil != err {
return nil, err
}
Expand Down Expand Up @@ -264,7 +264,7 @@ func getWhereConditions(where map[string]interface{}, ignoreKeys map[string]stru
comparables = append(comparables, OrWhere(orWhereComparable))
continue
}
field, operator, err = splitKey(key)
field, operator, err = splitKey(key, val)
if nil != err {
return nil, err
}
Expand Down Expand Up @@ -415,7 +415,7 @@ func convertInterfaceToMap(val interface{}) ([]interface{}, bool) {
return interfaceSlice, true
}

func splitKey(key string) (field string, operator string, err error) {
func splitKey(key string, val interface{}) (field string, operator string, err error) {
key = strings.Trim(key, " ")
if "" == key {
err = errSplitEmptyKey
Expand All @@ -425,6 +425,9 @@ func splitKey(key string) (field string, operator string, err error) {
if idx == -1 {
field = key
operator = "="
if reflect.ValueOf(val).Kind() == reflect.Slice {
operator = "in"
}
} else {
field = key[:idx]
operator = strings.Trim(key[idx+1:], " ")
Expand Down
17 changes: 10 additions & 7 deletions builder/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func TestBuildLockMode(t *testing.T) {
"foo": "bar",
"qq": "tt",
"age in": []interface{}{1, 3, 5, 7, 9},
"vx": []interface{}{1, 3, 5},
"faith <>": "Muslim",
"_or": []map[string]interface{}{
{
Expand Down Expand Up @@ -58,8 +59,8 @@ func TestBuildLockMode(t *testing.T) {
fields: []string{"id", "name", "age"},
},
out: outStruct{
cond: "SELECT id,name,age FROM tb WHERE (((aa=? AND bb=?) OR (((neeest_ff IN (?,?) AND neeest_ee!=?) OR (neeest_gg=? AND neeest_hh NOT IN (?,?))) AND cc=? AND dd IN (?,?))) AND foo=? AND qq=? AND age IN (?,?,?,?,?) AND faith!=?) GROUP BY department ORDER BY age DESC,score ASC LIMIT ?,? LOCK IN SHARE MODE",
vals: []interface{}{11, "xswl", 34, 59, "dw42", 1259, 358, 1245, "234", 7, 8, "bar", "tt", 1, 3, 5, 7, 9, "Muslim", 0, 100},
cond: "SELECT id,name,age FROM tb WHERE (((aa=? AND bb=?) OR (((neeest_ff IN (?,?) AND neeest_ee!=?) OR (neeest_gg=? AND neeest_hh NOT IN (?,?))) AND cc=? AND dd IN (?,?))) AND foo=? AND qq=? AND age IN (?,?,?,?,?) AND vx IN (?,?,?) AND faith!=?) GROUP BY department ORDER BY age DESC,score ASC LIMIT ?,? LOCK IN SHARE MODE",
vals: []interface{}{11, "xswl", 34, 59, "dw42", 1259, 358, 1245, "234", 7, 8, "bar", "tt", 1, 3, 5, 7, 9, 1, 3, 5, "Muslim", 0, 100},
err: nil,
},
},
Expand Down Expand Up @@ -157,13 +158,14 @@ func TestBuildHaving(t *testing.T) {
"_having": map[string]interface{}{
"total >=": 1000,
"total <": 50000,
"vx": []interface{}{1, 3, 5},
},
},
selectField: []string{"name, count(price) as total"},
},
out: outStruct{
cond: "SELECT name, count(price) as total FROM tb WHERE (age>?) GROUP BY name HAVING (total>=? AND total<?)",
vals: []interface{}{23, 1000, 50000},
cond: "SELECT name, count(price) as total FROM tb WHERE (age>?) GROUP BY name HAVING (vx IN (?,?,?) AND total>=? AND total<?)",
vals: []interface{}{23, 1, 3, 5, 1000, 50000},
err: nil,
},
},
Expand Down Expand Up @@ -519,6 +521,7 @@ func Test_BuildSelect(t *testing.T) {
"foo": "bar",
"qq": "tt",
"age in": []interface{}{1, 3, 5, 7, 9},
"vx": []interface{}{1, 3, 5},
"faith <>": "Muslim",
"_or": []map[string]interface{}{
{
Expand Down Expand Up @@ -547,8 +550,8 @@ func Test_BuildSelect(t *testing.T) {
fields: []string{"id", "name", "age"},
},
out: outStruct{
cond: "SELECT id,name,age FROM tb WHERE (((aa=? AND bb=?) OR (((neeest_ff IN (?,?) AND neeest_ee!=?) OR (neeest_gg=? AND neeest_hh NOT IN (?,?))) AND cc=? AND dd IN (?,?))) AND foo=? AND qq=? AND age IN (?,?,?,?,?) AND faith!=?) GROUP BY department ORDER BY age DESC,score ASC LIMIT ?,?",
vals: []interface{}{11, "xswl", 34, 59, "dw42", 1259, 358, 1245, "234", 7, 8, "bar", "tt", 1, 3, 5, 7, 9, "Muslim", 0, 100},
cond: "SELECT id,name,age FROM tb WHERE (((aa=? AND bb=?) OR (((neeest_ff IN (?,?) AND neeest_ee!=?) OR (neeest_gg=? AND neeest_hh NOT IN (?,?))) AND cc=? AND dd IN (?,?))) AND foo=? AND qq=? AND age IN (?,?,?,?,?) AND vx IN (?,?,?) AND faith!=?) GROUP BY department ORDER BY age DESC,score ASC LIMIT ?,?",
vals: []interface{}{11, "xswl", 34, 59, "dw42", 1259, 358, 1245, "234", 7, 8, "bar", "tt", 1, 3, 5, 7, 9, 1, 3, 5, "Muslim", 0, 100},
err: nil,
},
},
Expand Down Expand Up @@ -1314,4 +1317,4 @@ func TestInsertOnDuplicate(t *testing.T) {
ass.NoError(err)
ass.Equal("INSERT INTO tb (a,b,c) VALUES (?,?,?) ON DUPLICATE KEY UPDATE c=?", cond)
ass.Equal([]interface{}{1, 2, 3, 4}, vals)
}
}
13 changes: 11 additions & 2 deletions translation/zhcn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ builder不是一个ORM(我们开发Gendry的重要原因之一就是不喜欢O

```go
where := map[string]interface{}{
"city in": []string{"beijing", "shanghai"},
"city": []string{"beijing", "shanghai"},
// 默认可以省略 in 操作符,等同于:
// "city in": []string{"beijing", "shanghai"},
"score": 5,
"age >": 35,
"address": builder.IsNotNull,
Expand All @@ -61,6 +63,13 @@ cond, values, err := builder.BuildSelect(table, where, selectFields)
rows,err := db.Query(cond, values...)
```

默认 `where` 参数中可以根据value(reflect.Slice)类型来自动的添加 `in` 参数
```go
where := map[string]interface{}{
"city": []string{"beijing", "shanghai"},
}
```

如果你想清除where map中的零值可以使用 builder.OmitEmpty
``` go
where := map[string]interface{}{
Expand All @@ -78,7 +87,7 @@ finalWhere := builder.OmitEmpty(where, []string{"score", "age"})
```go
where := map[string]interface{}{
"score > ": 100,
"city in": []interface{}{"Beijing", "Shijiazhuang",}
"city": []interface{}{"Beijing", "Shijiazhuang",}
}
// AggregateSum,AggregateMax,AggregateMin,AggregateCount,AggregateAvg is supported
result, err := AggregateQuery(ctx, db, "tableName", where, AggregateSum("age"))
Expand Down