| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- package search
- import (
- "fmt"
- "reflect"
- "strings"
- )
- const (
- // FromQueryTag tag标记
- FromQueryTag = "search"
- // Mysql 数据库标识
- Mysql = "mysql"
- // Postgres 数据库标识
- Postgres = "postgres"
- )
- // ResolveSearchQuery 解析
- /**
- * exact / iexact 等于
- * contains / icontains 包含
- * gt / gte 大于 / 大于等于
- * lt / lte 小于 / 小于等于
- * startswith / istartswith 以…起始
- * endswith / iendswith 以…结束
- * in
- * isnull
- * order 排序 e.g. order[key]=desc order[key]=asc
- */
- func ResolveSearchQuery(driver string, q interface{}, condition Condition) {
- qType := reflect.TypeOf(q)
- qValue := reflect.ValueOf(q)
- var tag string
- var ok bool
- var t *resolveSearchTag
- //var sep = "`"
- //if driver == Postgres {
- // sep = "\""
- //}
- for i := 0; i < qType.NumField(); i++ {
- tag, ok = "", false
- tag, ok = qType.Field(i).Tag.Lookup(FromQueryTag)
- if !ok {
- //递归调用
- ResolveSearchQuery(driver, qValue.Field(i).Interface(), condition)
- continue
- }
- switch tag {
- case "-":
- continue
- }
- t = makeTag(tag)
- if qValue.Field(i).IsZero() {
- continue
- }
- //解析 Postgres `语法不支持,单独适配
- if driver == Postgres {
- pgSql(driver, t, condition, qValue, i)
- } else {
- otherSql(driver, t, condition, qValue, i)
- }
- }
- }
- func pgSql(driver string, t *resolveSearchTag, condition Condition, qValue reflect.Value, i int) {
- switch t.Type {
- case "left":
- //左关联
- join := condition.SetJoinOn(t.Type, fmt.Sprintf(
- "left join %s on %s.%s = %s.%s", t.Join, t.Join, t.On[0], t.Table, t.On[1],
- ))
- ResolveSearchQuery(driver, qValue.Field(i).Interface(), join)
- case "exact", "iexact":
- condition.SetWhere(fmt.Sprintf("%s.%s = ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "icontains":
- condition.SetWhere(fmt.Sprintf("%s.%s ilike ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String() + "%"})
- case "contains":
- condition.SetWhere(fmt.Sprintf("%s.%s like ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String() + "%"})
- case "gt":
- condition.SetWhere(fmt.Sprintf("%s.%s > ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "gte":
- condition.SetWhere(fmt.Sprintf("%s.%s >= ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "lt":
- condition.SetWhere(fmt.Sprintf("%s.%s < ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "lte":
- condition.SetWhere(fmt.Sprintf("%s.%s <= ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "istartswith":
- condition.SetWhere(fmt.Sprintf("%s.%s ilike ?", t.Table, t.Column), []interface{}{qValue.Field(i).String() + "%"})
- case "startswith":
- condition.SetWhere(fmt.Sprintf("%s.%s like ?", t.Table, t.Column), []interface{}{qValue.Field(i).String() + "%"})
- case "iendswith":
- condition.SetWhere(fmt.Sprintf("%s.%s ilike ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String()})
- case "endswith":
- condition.SetWhere(fmt.Sprintf("%s.%s like ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String()})
- case "in":
- condition.SetWhere(fmt.Sprintf("%s.%s in (?)", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "isnull":
- if !(qValue.Field(i).IsZero() && qValue.Field(i).IsNil()) {
- condition.SetWhere(fmt.Sprintf("%s.%s isnull", t.Table, t.Column), make([]interface{}, 0))
- }
- case "order":
- switch strings.ToLower(qValue.Field(i).String()) {
- case "desc", "asc":
- condition.SetOrder(fmt.Sprintf("%s.%s %s", t.Table, t.Column, qValue.Field(i).String()))
- }
- }
- }
- func otherSql(driver string, t *resolveSearchTag, condition Condition, qValue reflect.Value, i int) {
- switch t.Type {
- case "left":
- //左关联
- join := condition.SetJoinOn(t.Type, fmt.Sprintf(
- "left join `%s` on `%s`.`%s` = `%s`.`%s`",
- t.Join,
- t.Join,
- t.On[0],
- t.Table,
- t.On[1],
- ))
- ResolveSearchQuery(driver, qValue.Field(i).Interface(), join)
- case "exact", "iexact":
- condition.SetWhere(fmt.Sprintf("`%s`.`%s` = ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "contains", "icontains":
- condition.SetWhere(fmt.Sprintf("`%s`.`%s` like ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String() + "%"})
- case "gt":
- condition.SetWhere(fmt.Sprintf("`%s`.`%s` > ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "gte":
- condition.SetWhere(fmt.Sprintf("`%s`.`%s` >= ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "lt":
- condition.SetWhere(fmt.Sprintf("`%s`.`%s` < ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "lte":
- condition.SetWhere(fmt.Sprintf("`%s`.`%s` <= ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "startswith", "istartswith":
- condition.SetWhere(fmt.Sprintf("`%s`.`%s` like ?", t.Table, t.Column), []interface{}{qValue.Field(i).String() + "%"})
- case "endswith", "iendswith":
- condition.SetWhere(fmt.Sprintf("`%s`.`%s` like ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String()})
- case "in":
- condition.SetWhere(fmt.Sprintf("`%s`.`%s` in (?)", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
- case "isnull":
- if !(qValue.Field(i).IsZero() && qValue.Field(i).IsNil()) {
- condition.SetWhere(fmt.Sprintf("`%s`.`%s` isnull", t.Table, t.Column), make([]interface{}, 0))
- }
- case "order":
- switch strings.ToLower(qValue.Field(i).String()) {
- case "desc", "asc":
- condition.SetOrder(fmt.Sprintf("`%s`.`%s` %s", t.Table, t.Column, qValue.Field(i).String()))
- }
- }
- }
|