rest/condition.go

145 lines
4.1 KiB
Go
Raw Normal View History

2024-12-11 17:29:01 +08:00
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
}