From becd38a899fa769e2a1d8deddc84a71fd6f2467e Mon Sep 17 00:00:00 2001 From: zhnlviing Date: Fri, 22 Jul 2022 20:31:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=89=20=5For=20=E5=89=8D=E7=BC=80=E7=9A=84?= =?UTF-8?q?=E5=8D=B3=E8=AE=A4=E4=B8=BA=E6=98=AF=20or=20=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=EF=BC=8C=E8=BF=99=E6=A0=B7=E5=8F=AF=E4=BB=A5=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=20or=20=E6=9D=A1=E4=BB=B6=20(#130)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 有 _or 前缀的即认为是 or 语句,这样可以支持多个 or 条件 * 补充单元测试 Test_BuildSelectMutliOr * 补充文档:多个 or 语句如何使用 Co-authored-by: 张弘年 --- README.md | 21 ++++++++++++++ builder/builder.go | 2 +- builder/builder_test.go | 59 ++++++++++++++++++++++++++++++++++++++ translation/zhcn/README.md | 21 ++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 624d8ae..270d074 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,28 @@ result, err = AggregateQuery(ctx, db, "tableName", where, AggregateAvg("score")) averageScore := result.Float64() ``` +multi `or` condition can use multi `_or` prefix string mark +``` go +where := map[string]interface{}{ + // location + "_or_location": []map[string]interface{}{{ + "subway": "beijing_15", + }, { + "district": "Chaoyang", + }}, + // functions + "_or_functions": []map[string]interface{}{{ + "has_gas": true, + }, { + "has_lift": true, +}}} + +// query = (((subway=?) OR (district=?)) AND ((has_gas=?) OR (has_lift=?))) +// args = ["beijing_15", "Chaoyang", true, true] +``` + If you want to clear the value '0' in the where map, you can use builder.OmitEmpty + ``` go where := map[string]interface{}{ "score": 0, diff --git a/builder/builder.go b/builder/builder.go index 0dc447b..773664e 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -242,7 +242,7 @@ func getWhereConditions(where map[string]interface{}, ignoreKeys map[string]stru if _, ok := ignoreKeys[key]; ok { continue } - if key == "_or" { + if strings.HasPrefix(key, "_or") { var ( orWheres []map[string]interface{} orWhereComparable []Comparable diff --git a/builder/builder_test.go b/builder/builder_test.go index 54ae426..219e39e 100644 --- a/builder/builder_test.go +++ b/builder/builder_test.go @@ -608,6 +608,65 @@ func Test_BuildSelect(t *testing.T) { } } +func Test_BuildSelectMutliOr(t *testing.T) { + type inStruct struct { + table string + where map[string]interface{} + fields []string + } + type outStruct struct { + cond string + vals []interface{} + err error + } + var data = []struct { + in inStruct + out outStruct + }{ + { + in: inStruct{ + table: "tb", + where: map[string]interface{}{ + "a": 1, + "_or": []map[string]interface{}{ + { + "b": 2, + "c": 3, + }, + { + "d": 4, + "e": 5, + }, + }, + "_or2": []map[string]interface{}{ + { + "b2": 22, + "c2": 33, + }, + { + "d2": 44, + "e2": 55, + }, + }, + }, + fields: []string{"id", "name", "age"}, + }, + out: outStruct{ + cond: "SELECT id,name,age FROM tb WHERE (((b=? AND c=?) OR (d=? AND e=?)) AND ((b2=? AND c2=?) OR (d2=? AND e2=?)) AND a=?)", + vals: []interface{}{2, 3, 4, 5, 22, 33, 44, 55, 1}, + err: nil, + }, + }, + } + ass := assert.New(t) + for _, tc := range data { + cond, vals, err := BuildSelect(tc.in.table, tc.in.where, tc.in.fields) + ass.Equal(tc.out.err, err) + ass.Equal(tc.out.cond, cond) + ass.Equal(tc.out.vals, vals) + } +} + func BenchmarkBuildSelect_Sequelization(b *testing.B) { for i := 0; i < b.N; i++ { _, _, err := BuildSelect("tb", map[string]interface{}{ diff --git a/translation/zhcn/README.md b/translation/zhcn/README.md index 93da080..85e057f 100644 --- a/translation/zhcn/README.md +++ b/translation/zhcn/README.md @@ -70,6 +70,27 @@ where := map[string]interface{}{ } ``` +如果你有多个 `or` 条件可以是用 `_or` 前缀开头的字符串来标识 `or` 语句 +``` go +where := map[string]interface{}{ + // 位置条件(15号线或朝阳区) + "_or_location": []map[string]interface{}{{ + "subway": "beijing_15", + }, { + "district": "Chaoyang", + }}, + // 类型(有煤气或有电梯) + "_or_functions": []map[string]interface{}{{ + "has_gas": true, + }, { + "has_lift": true, + }}, +} + +// query = (((subway=?) OR (district=?)) AND ((has_gas=?) OR (has_lift=?))) +// args = ["beijing_15", "Chaoyang", true, true] +``` + 如果你想清除where map中的零值可以使用 builder.OmitEmpty ``` go where := map[string]interface{}{