代码拉取完成,页面将自动刷新
package search
import (
"fmt"
"reflect"
"strings"
"gorm.io/gorm/schema"
)
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) Condition {
qType := reflect.TypeOf(q)
qValue := reflect.ValueOf(q)
switch qType.Kind() {
case reflect.Ptr:
qType = qType.Elem()
qValue = qValue.Elem()
case reflect.Struct:
break
default:
return condition
}
var tag string
var ok bool
var t *resolveSearchTag
//var sep = "`"
//if driver == Postgres {
// sep = "\""
//}
table := ""
if tabler, ok := q.(schema.Tabler); ok {
table = tabler.TableName()
}
for i := 0; i < qType.NumField(); i++ {
tag, ok = "", false
f := qType.Field(i)
tag, ok = f.Tag.Lookup(FromQueryTag)
if !ok && f.Anonymous {
//递归调用
ResolveSearchQuery(driver, qValue.Field(i).Interface(), condition)
continue
}
switch tag {
case "-", "":
continue
}
t = makeTag(tag)
if t.Table == "" {
t.Table = table
}
if t.Column == "" {
if gormTag, ok := qType.Field(i).Tag.Lookup("gorm"); ok {
t.Column = getGormColumn(gormTag)
}
if t.Column == "" {
t.Column = snakeString(qType.Field(i).Name)
}
}
if qValue.Field(i).IsZero() {
continue
}
//解析 Postgres `语法不支持,单独适配
if driver == Postgres {
pgSql(driver, t, condition, qValue, i)
} else {
otherSql(driver, t, condition, qValue, i)
}
}
return condition
}
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 "glt":
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()))
}
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。