package rest import ( "context" "encoding/json" "git.nobla.cn/golang/kos/util/arrays" "git.nobla.cn/golang/rest/types" "net/http" "strings" ) func findCondition(schema *types.Schema, conditions []*types.Condition) *types.Condition { for _, cond := range conditions { if cond.Column == schema.Column { return cond } } return nil } func BuildConditions(ctx context.Context, r *http.Request, query *Query, schemas []*types.Schema) (err error) { var ( ok bool skip bool formValue string activeQuery ActiveQuery ) if activeQuery, ok = query.Model().(ActiveQuery); ok { if err = activeQuery.BeforeQuery(ctx, query); err != nil { return } } if arrays.Exists(r.Method, []string{http.MethodPut, http.MethodPost}) { conditions := make([]*types.Condition, 0) if err = json.NewDecoder(r.Body).Decode(&conditions); err != nil { return } for _, row := range schemas { if row.Native == 0 { continue } cond := findCondition(row, conditions) if cond == nil { continue } switch row.Format { case types.FormatInteger, types.FormatFloat, types.FormatTimestamp, types.FormatDatetime, types.FormatDate, types.FormatTime: switch cond.Expr { case types.OperatorBetween: if len(cond.Values) == 2 { query.AndFilterWhere(newCondition(row.Column, cond.Values[0]).WithExpr(">=")) query.AndFilterWhere(newCondition(row.Column, cond.Values[1]).WithExpr("<=")) } case types.OperatorGreaterThan: query.AndFilterWhere(newCondition(row.Column, cond.Value).WithExpr(">")) case types.OperatorGreaterEqual: query.AndFilterWhere(newCondition(row.Column, cond.Value).WithExpr(">=")) case types.OperatorLessThan: query.AndFilterWhere(newCondition(row.Column, cond.Value).WithExpr("<")) case types.OperatorLessEqual: query.AndFilterWhere(newCondition(row.Column, cond.Value).WithExpr("<=")) default: query.AndFilterWhere(newCondition(row.Column, cond.Value)) } default: switch cond.Expr { case types.OperatorLike: query.AndFilterWhere(newCondition(row.Column, cond.Value).WithExpr("LIKE")) default: query.AndFilterWhere(newCondition(row.Column, cond.Value)) } } } } else { qs := r.URL.Query() for _, row := range schemas { skip = false if skip { continue } if row.Native == 0 { continue } formValue = qs.Get(row.Column) switch row.Format { case types.FormatString, types.FormatText: if row.Attribute.Match == types.MatchExactly { query.AndFilterWhere(newCondition(row.Column, formValue)) } else { query.AndFilterWhere(newCondition(row.Column, formValue).WithExpr("LIKE")) } case types.FormatTime, types.FormatDate, types.FormatDatetime, types.FormatTimestamp: var sep string seps := []byte{',', '/'} for _, s := range seps { if strings.IndexByte(formValue, s) > -1 { sep = string(s) } } if ss := strings.Split(formValue, sep); len(ss) == 2 { query.AndFilterWhere( newCondition(row.Column, strings.TrimSpace(ss[0])).WithExpr(">="), newCondition(row.Column, strings.TrimSpace(ss[1])).WithExpr("<="), ) } else { query.AndFilterWhere(newCondition(row.Column, formValue)) } case types.FormatInteger, types.FormatFloat: query.AndFilterWhere(newCondition(row.Column, formValue)) default: if row.Type == types.TypeString { if row.Attribute.Match == types.MatchExactly { query.AndFilterWhere(newCondition(row.Column, formValue)) } else { query.AndFilterWhere(newCondition(row.Column, formValue).WithExpr("LIKE")) } } else { query.AndFilterWhere(newCondition(row.Column, formValue)) } } } } sortPar := r.FormValue("sort") if sortPar != "" { sorts := strings.Split(sortPar, ",") for _, s := range sorts { if s[0] == '-' { query.OrderBy(s[1:], "DESC") } else { if s[0] == '+' { query.OrderBy(s[1:], "ASC") } else { query.OrderBy(s, "ASC") } } } } if activeQuery, ok = query.Model().(ActiveQuery); ok { if err = activeQuery.AfterQuery(ctx, query); err != nil { return } } return }