| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- // Copyright (c) 2015 qianqiusoft.com
- // Licensed to You under the GNU Affero GPL v3
- // See the LICENSE file at git.qianqiusoft.com/qianqiusoft/light-vocation/LICENSE
- // http://www.gnu.org/licenses/why-affero-gpl.en.html
- package models
- import (
- "encoding/json"
- "errors"
- "fmt"
- "strings"
- )
- const (
- _RULE_DATA_TYPE_FIELD_NAME = "field_name"
- _RULE_DATA_TYPE_USER_VALUE = "user_value"
- _RULE_DATA_TYPE_FIELD_VALUE = "field_value"
- )
- type Filter struct {
- GroupOp string `json:"groupOp"`
- Rules []*FilterField `json:"rules"`
- Groups []*Filter `json:"groups"`
- }
- type FilterField struct {
- Field string `json:"field"`
- Op string `json:"op"`
- Data string `json:"data"`
- }
- /**
- * @brief new filter by string
- * @param filtersStr json data of filter
- *
- * @return point of Filter
- * @return error
- */
- func NewFilter(filtersStr string) (*Filter, error) {
- filters := &Filter{}
- err := json.Unmarshal([]byte(filtersStr), filters)
- if err != nil {
- return nil, err
- }
- return filters, nil
- }
- /**
- * @brief parse the filter
- *
- * @return select querybuilder
- * @return count select querybuilder
- * @return error
- */
- func (this *Filter) Parse(tableName string) (string, []interface{}, error) {
- whereStatement := ""
- groupWhereStatement := ""
- datas := make([]interface{}, 0)
- isAnd := true
- if strings.ToLower(strings.TrimSpace(this.GroupOp)) == "or" {
- isAnd = false
- }
- if len(this.Rules) > 0 {
- whereStr, ruleDatas := this.ParseRule(tableName, this.Rules[0])
- if whereStr != "" {
- whereStatement = whereStr
- for _, ruleData := range ruleDatas {
- datas = append(datas, ruleData)
- }
- } else {
- return whereStatement, datas, errors.New(fmt.Sprintf("the 0 rule is invalid"))
- }
- for i := 1; i < len(this.Rules); i++ {
- whereStr, ruleDatas = this.ParseRule(tableName, this.Rules[i])
- if whereStr != "" {
- if isAnd {
- whereStatement += " AND " + whereStr
- } else {
- whereStatement += " OR " + whereStr
- }
- for _, ruleData := range ruleDatas {
- datas = append(datas, ruleData)
- }
- } else {
- return whereStatement, datas, errors.New(fmt.Sprintf("the %d rule is invalid", i))
- }
- }
- }
- if len(this.Groups) > 0 {
- whereStr, groupDatas, err := this.Groups[0].Parse(tableName)
- if err != nil {
- return whereStatement, datas, err
- }
- if whereStr != "" {
- groupWhereStatement = whereStr
- for _, groupData := range groupDatas {
- datas = append(datas, groupData)
- }
- } else {
- return whereStatement, datas, errors.New("the 0 group is invalid")
- }
- for i := 1; i < len(this.Groups); i++ {
- whereStr, groupDatas, err := this.Groups[i].Parse(tableName)
- if err != nil {
- return whereStatement, datas, err
- }
- if whereStr != "" {
- if isAnd {
- groupWhereStatement += " AND " + whereStr
- } else {
- groupWhereStatement += " OR " + whereStr
- }
- for _, groupData := range groupDatas {
- datas = append(datas, groupData)
- }
- } else {
- return whereStatement, datas, errors.New(fmt.Sprintf("the %d group is invalid", i))
- }
- }
- if groupWhereStatement != "" {
- groupWhereStatement = "(" + groupWhereStatement + ")"
- }
- }
- if whereStatement == "" {
- whereStatement = groupWhereStatement
- } else {
- whereStatement = "(" + whereStatement + ")"
- if groupWhereStatement != "" {
- if isAnd {
- whereStatement += " AND " + groupWhereStatement
- } else {
- whereStatement += " OR " + groupWhereStatement
- }
- }
- }
- return whereStatement, datas, nil
- }
- func (this *Filter) ParseRule(tableName string, field *FilterField) (string, []interface{}) {
- switch ruleDataType(field.Field) {
- case _RULE_DATA_TYPE_FIELD_NAME:
- return ParsePureRule(tableName, field)
- case _RULE_DATA_TYPE_FIELD_VALUE:
- // if strings.HasSuffix(field.Field, ".org") {
- // a, b, _ := parseFieldOrgRule(field, tableName, nil)
- // return a, b
- // return "", make([]interface{}, 0)
- // } else {
- // return "", make([]interface{}, 0)
- // }
- return "", make([]interface{}, 0)
- default:
- return "", make([]interface{}, 0)
- }
- }
- func ParsePureRule(tableName string, field *FilterField) (string, []interface{}) {
- datas := make([]interface{}, 0)
- if field == nil {
- return "", datas
- }
- fData := FormatData(field.Op, field.Data)
- switch fData.(type) {
- case string:
- {
- if len(fData.(string)) >= 0 {
- datas = append(datas, fData)
- }
- }
- case []string:
- {
- fDataArr := fData.([]string)
- for _, arr := range fDataArr {
- if len(arr) > 0 {
- datas = append(datas, arr)
- }
- }
- }
- }
- whereStr := FormatOp(tableName, field.Op, field.Field, field.Data)
- if len(whereStr) > 0 {
- return whereStr, datas
- } else {
- return "", datas
- }
- }
- func FormatOp(table, op, field, data string) string {
- if strings.Contains(field, ".") {
- // the field is "talbe.field"
- switch strings.ToLower(op) {
- case "eq":
- {
- return fmt.Sprintf(" %s = ? ", field)
- }
- case "ne":
- {
- return fmt.Sprintf(" %s <> ? ", field)
- }
- case "lt":
- {
- return fmt.Sprintf(" %s < ? ", field)
- }
- case "le":
- {
- return fmt.Sprintf(" %s <= ? ", field)
- }
- case "gt":
- {
- return fmt.Sprintf(" %s > ? ", field)
- }
- case "ge":
- {
- return fmt.Sprintf(" %s >= ? ", field)
- }
- case "bw":
- {
- return fmt.Sprintf(" %s LIKE ? ", field)
- }
- case "bn":
- {
- return fmt.Sprintf(" %s NOT LIKE ? ", field)
- }
- case "ew":
- {
- return fmt.Sprintf(" %s LIKE ? ", field)
- }
- case "en":
- {
- return fmt.Sprintf(" %s NOT LIKE ? ", field)
- }
- case "cn":
- {
- return fmt.Sprintf(" %s LIKE ? ", field)
- }
- case "nc":
- {
- return fmt.Sprintf(" %s NOT LIKE ? ", field)
- }
- case "nu":
- {
- return fmt.Sprintf(" %s IS NULL ", field)
- }
- case "nn":
- {
- return fmt.Sprintf(" %s IS NOT NULL ", field)
- }
- case "date-cn":
- {
- return fmt.Sprintf(" %s >= ? and %s <= ? ", field, field)
- }
- case "in":
- {
- dataArr := strings.Split(data, ",")
- params := ""
- for _, arr := range dataArr {
- if len(arr) > 0 {
- params += "?,"
- }
- }
- params = strings.TrimRight(params, ",")
- if len(params) > 0 {
- return fmt.Sprintf(" %s IN (%s)", field, params)
- }
- }
- case "ni":
- {
- dataArr := strings.Split(data, ",")
- params := ""
- for _, arr := range dataArr {
- if len(arr) > 0 {
- params += "?,"
- }
- }
- params = strings.TrimRight(params, ",")
- if len(params) > 0 {
- return fmt.Sprintf(" %s NOT IN (%s)", field, params)
- }
- }
- }
- } else {
- if table == "" {
- switch strings.ToLower(op) {
- case "eq":
- {
- return fmt.Sprintf(" `%s` = ? ", field)
- }
- case "ne":
- {
- return fmt.Sprintf(" `%s` <> ? ", field)
- }
- case "lt":
- {
- return fmt.Sprintf(" `%s` < ? ", field)
- }
- case "le":
- {
- return fmt.Sprintf(" `%s` <= ? ", field)
- }
- case "gt":
- {
- return fmt.Sprintf(" `%s` > ? ", field)
- }
- case "ge":
- {
- return fmt.Sprintf(" `%s` >= ? ", field)
- }
- case "bw":
- {
- return fmt.Sprintf(" `%s` LIKE ? ", field)
- }
- case "bn":
- {
- return fmt.Sprintf(" `%s` NOT LIKE ? ", field)
- }
- case "ew":
- {
- return fmt.Sprintf(" `%s` LIKE ? ", field)
- }
- case "en":
- {
- return fmt.Sprintf(" `%s` NOT LIKE ? ", field)
- }
- case "cn":
- {
- return fmt.Sprintf(" `%s` LIKE ? ", field)
- }
- case "nc":
- {
- return fmt.Sprintf(" `%s` NOT LIKE ? ", field)
- }
- case "nu":
- {
- return fmt.Sprintf(" `%s` IS NULL ", field)
- }
- case "nn":
- {
- return fmt.Sprintf(" `%s` IS NOT NULL ", field)
- }
- case "date-cn":
- {
- return fmt.Sprintf(" %s >= ? and %s <= ? ", field, field)
- }
- case "in":
- {
- dataArr := strings.Split(data, ",")
- params := ""
- for _, arr := range dataArr {
- if len(arr) > 0 {
- params += "?,"
- }
- }
- params = strings.TrimRight(params, ",")
- if len(params) > 0 {
- return fmt.Sprintf(" `%s` IN (%s)", field, params)
- }
- }
- case "ni":
- {
- dataArr := strings.Split(data, ",")
- params := ""
- for _, arr := range dataArr {
- if len(arr) > 0 {
- params += "?,"
- }
- }
- params = strings.TrimRight(params, ",")
- if len(params) > 0 {
- return fmt.Sprintf(" `%s` NOT IN (%s)", field, params)
- }
- }
- }
- } else {
- switch strings.ToLower(op) {
- case "eq":
- {
- return fmt.Sprintf(" %s.%s = ? ", table, field)
- }
- case "ne":
- {
- return fmt.Sprintf(" %s.%s <> ? ", table, field)
- }
- case "lt":
- {
- return fmt.Sprintf(" %s.%s < ? ", table, field)
- }
- case "le":
- {
- return fmt.Sprintf(" %s.%s <= ? ", table, field)
- }
- case "gt":
- {
- return fmt.Sprintf(" %s.%s > ? ", table, field)
- }
- case "ge":
- {
- return fmt.Sprintf(" %s.%s >= ? ", table, field)
- }
- case "bw":
- {
- return fmt.Sprintf(" %s.%s LIKE ? ", table, field)
- }
- case "bn":
- {
- return fmt.Sprintf(" %s.%s NOT LIKE ? ", table, field)
- }
- case "ew":
- {
- return fmt.Sprintf(" %s.%s LIKE ? ", table, field)
- }
- case "en":
- {
- return fmt.Sprintf(" %s.%s NOT LIKE ? ", table, field)
- }
- case "cn":
- {
- return fmt.Sprintf(" %s.%s LIKE ? ", table, field)
- }
- case "nc":
- {
- return fmt.Sprintf(" %s.%s NOT LIKE ? ", table, field)
- }
- case "nu":
- {
- return fmt.Sprintf(" %s.%s IS NULL ", table, field)
- }
- case "nn":
- {
- return fmt.Sprintf(" %s.%s IS NOT NULL ", table, field)
- }
- case "date-cn":
- {
- return fmt.Sprintf(" %s.%s >= ? and %s.%s <= ? ", table, field, table, field)
- }
- case "in":
- {
- dataArr := strings.Split(data, ",")
- params := ""
- for _, arr := range dataArr {
- if len(arr) > 0 {
- params += "?,"
- }
- }
- params = strings.TrimRight(params, ",")
- if len(params) > 0 {
- return fmt.Sprintf(" %s.%s IN (%s)", table, field, params)
- }
- }
- case "ni":
- {
- dataArr := strings.Split(data, ",")
- params := ""
- for _, arr := range dataArr {
- if len(arr) > 0 {
- params += "?,"
- }
- }
- params = strings.TrimRight(params, ",")
- if len(params) > 0 {
- return fmt.Sprintf(" %s.%s NOT IN (%s)", table, field, params)
- }
- }
- }
- }
- }
- return ""
- }
- func FormatData(op, data string) interface{} {
- switch strings.ToLower(op) {
- case "eq", "ne", "lt", "le", "gt", "ge":
- {
- return data
- }
- case "bw":
- {
- return fmt.Sprintf("%s%%", data)
- }
- case "bn":
- {
- return fmt.Sprintf("%s%%", data)
- }
- case "ew":
- {
- return fmt.Sprintf("%%%s", data)
- }
- case "en":
- {
- return fmt.Sprintf("%%%s", data)
- }
- case "cn":
- {
- return fmt.Sprintf("%%%s%%", data)
- }
- case "nc":
- {
- return fmt.Sprintf("%%%s%%", data)
- }
- case "in":
- {
- return strings.Split(data, ",")
- }
- case "ni":
- {
- return strings.Split(data, ",")
- }
- case "date-cn":
- {
- data = strings.TrimSpace(data)
- if data == "" {
- return []string{"", ""}
- } else {
- data = data[0:10]
- return []string{data + " 00:00:00", data + " 23:59:59"}
- }
- }
- }
- return ""
- }
- func formatData(op, data string) interface{} {
- return FormatData(op, data)
- }
- func formatOp(table, op, field, data string) string {
- return FormatOp(table, op, field, data)
- }
- // where the value begin with $, return user_value
- // where the value begin with #, return field_value
- // where the value begin with letter, return value
- func ruleDataType(data string) string {
- data = strings.TrimSpace(data)
- if strings.HasPrefix(data, "$") {
- return _RULE_DATA_TYPE_USER_VALUE
- } else if strings.HasPrefix(data, "#") {
- return _RULE_DATA_TYPE_FIELD_VALUE
- } else {
- return _RULE_DATA_TYPE_FIELD_NAME
- }
- }
|