From 40f1beda54569da46f9e8b5090d081cf0530fd77 Mon Sep 17 00:00:00 2001 From: Mac Date: Mon, 14 Oct 2024 12:15:05 +0800 Subject: [PATCH] feat: add ADD where cond query --- builder/README.md | 51 +++++++++++++++++++++++++++++++++++ builder/builder.go | 22 +++++++++++++++ builder/builder_test.go | 59 +++++++++++++++++++++++++++++++++++++++++ builder/dao.go | 11 ++++++++ 4 files changed, 143 insertions(+) diff --git a/builder/README.md b/builder/README.md index 6af8d5a..65b5b91 100644 --- a/builder/README.md +++ b/builder/README.md @@ -50,6 +50,47 @@ func main() { //cond: SELECT name,count(price) as total,age FROM tableName WHERE (name=? AND (? MEMBER OF(my_json->'$.list')) AND ((x1=? AND x2>=?) OR (x3=? AND x4!=?)) AND country=? AND role=? AND age>? AND gmt_create? AND total<=?) ORDER BY age desc //vals: []interface{}{"name0", 1, 11, 45, "234", "tx2", "China", "driver", 45, 1000, 50000} + + notDelWhere := map[string]interface{}{ + "is_del": 0, + } + + bllWhere := map[string]interface{}{ + "_custom_0": builder.Custom("name=?", "name0"), + "_custom_1": builder.JsonContains("my_json->'$.list'", 1), + "country": "China", + "role": "driver", + "age >": 45, + "gmt_create <": builder.Raw("gmt_modified"), + "_or": []map[string]interface{}{ + { + "x1": 11, + "x2 >=": 45, + }, + { + "x3": "234", + "x4 <>": "tx2", + }, + }, + } + + aopWhere := map[string]interface{}{ + "_and": []map[string]interface{}{ + notDelWhere, + bllWhere, + }, + "_groupby": "name", + "_having": map[string]interface{}{ + "total >": 1000, + "total <=": 50000, + }, + "_orderby": "age desc", + } + + condAop,valsAop,err := builder.BuildSelect("tableName", where, []string{"name", "count(price) as total", "age"}) + + //condAop: SELECT name,count(price) as total,age FROM tableName WHERE (((is_del=?) AND (name=? AND (? MEMBER OF(my_json->'$.list')) AND ((x1=? AND x2>=?) OR (x3=? AND x4!=?)) AND country=? AND role=? AND age>? AND gmt_create? AND total<=?) ORDER BY age desc + //valsAop: [0 name0 1 11 45 234 tx2 China driver 45 1000 50000] if nil != err { panic(err) @@ -114,6 +155,7 @@ others supported: * _limit * _lockMode * _custom_xxx +* _and ``` go where := map[string]interface{}{ @@ -135,6 +177,15 @@ where := map[string]interface{}{ "_limit": []uint{offset, row_count}, "_lockMode": "share", } + +aopWhere := map[string]interface{}{ + "_and_soft_deleted": []map[string]interface{}{ + { + "is_del": 1, + }, + where, + } +} ``` Note: * _having will be ignored if _groupby isn't setted diff --git a/builder/builder.go b/builder/builder.go index 98ebd5e..7681dd9 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -295,6 +295,28 @@ func getWhereConditions(where map[string]interface{}, ignoreKeys map[string]stru comparables = append(comparables, v) continue } + if strings.HasPrefix(key, "_and") { + var ( + andWheres []map[string]interface{} + andWhereComparable []Comparable + ok bool + ) + if andWheres, ok = val.([]map[string]interface{}); !ok { + return nil, errOrValueType + } + for _, andWhere := range andWheres { + if andWhere == nil { + continue + } + andNestWhere, err := getWhereConditions(andWhere, ignoreKeys) + if nil != err { + return nil, err + } + andWhereComparable = append(andWhereComparable, NestWhere(andNestWhere)) + } + comparables = append(comparables, AndWhere(andWhereComparable)) + continue + } field, operator, err = splitKey(key, val) if nil != err { return nil, err diff --git a/builder/builder_test.go b/builder/builder_test.go index b120f3c..1bb4b7d 100644 --- a/builder/builder_test.go +++ b/builder/builder_test.go @@ -668,6 +668,65 @@ func Test_BuildSelectMultiOr(t *testing.T) { } } +func Test_BuildSelectMultiAnd(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{}{ + "col1": 1, + "_and": []map[string]interface{}{ + { + "aop1_1": 2, + "aop1_2": 3, + }, + { + "bll1": 4, + "bll2": 5, + }, + }, + "_and2": []map[string]interface{}{ + { + "aop2_1": 22, + "aop2_2": 33, + }, + { + "bll3": 44, + "bll4": 55, + }, + }, + }, + fields: []string{"id", "name", "age"}, + }, + out: outStruct{ + cond: "SELECT id,name,age FROM tb WHERE (((aop1_1=? AND aop1_2=?) AND (bll1=? AND bll2=?)) AND ((aop2_1=? AND aop2_2=?) AND (bll3=? AND bll4=?)) AND col1=?)", + 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/builder/dao.go b/builder/dao.go index 7c0fb9a..3662172 100644 --- a/builder/dao.go +++ b/builder/dao.go @@ -296,6 +296,17 @@ func (ow OrWhere) Build() ([]string, []interface{}) { return cond, vals } +type AndWhere []Comparable + +func (aw AndWhere) Build() ([]string, []interface{}) { + var cond []string + var vals []interface{} + andWhereString, andWhereVals := whereConnector("AND", aw...) + cond = append(cond, andWhereString) + vals = andWhereVals + return cond, vals +} + func build(m map[string]interface{}, op string) ([]string, []interface{}) { if nil == m || 0 == len(m) { return nil, nil