Skip to content
Open
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
51 changes: 51 additions & 0 deletions builder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<gmt_modified) GROUP BY name HAVING (total>? 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<gmt_modified))) GROUP BY name HAVING (total>? AND total<=?) ORDER BY age desc
//valsAop: [0 name0 1 11 45 234 tx2 China driver 45 1000 50000]

if nil != err {
panic(err)
Expand Down Expand Up @@ -114,6 +155,7 @@ others supported:
* _limit
* _lockMode
* _custom_xxx
* _and

``` go
where := map[string]interface{}{
Expand All @@ -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
Expand Down
22 changes: 22 additions & 0 deletions builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
59 changes: 59 additions & 0 deletions builder/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}{
Expand Down
11 changes: 11 additions & 0 deletions builder/dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down