first commit
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
package condition
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"git.fsdpf.net/go/contracts"
|
||||
"git.fsdpf.net/go/db"
|
||||
"github.com/samber/lo"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type ConditionExpr struct {
|
||||
parent contracts.Condition
|
||||
operator contracts.ConditionOperator
|
||||
field string
|
||||
fieldResource string
|
||||
fieldSqlFunc string
|
||||
fieldSqlFuncParam string
|
||||
ignoreEmptyParma bool
|
||||
tokenType contracts.ConditionTokenType
|
||||
token string
|
||||
matchPrefix string // 匹配前缀
|
||||
}
|
||||
|
||||
func (this ConditionExpr) GetOperator() contracts.ConditionOperator {
|
||||
return this.operator
|
||||
}
|
||||
|
||||
func (this *ConditionExpr) SetMatchPrefix(s string) contracts.ConditionExpr {
|
||||
this.matchPrefix = s
|
||||
return this
|
||||
}
|
||||
|
||||
func (this ConditionExpr) GetField() string {
|
||||
return this.field
|
||||
}
|
||||
|
||||
func (this ConditionExpr) GetFieldResource() string {
|
||||
return this.fieldResource
|
||||
}
|
||||
|
||||
func (this *ConditionExpr) AppendTo(c contracts.Condition) {
|
||||
this.parent = c
|
||||
}
|
||||
|
||||
func (this ConditionExpr) ToSql(m contracts.ModelParam) db.Expression {
|
||||
first := "`" + this.fieldResource + "`.`" + this.field + "`"
|
||||
|
||||
if strings.Contains(this.field, "->") {
|
||||
first = "`" + this.fieldResource + "`." + this.field + ""
|
||||
}
|
||||
|
||||
value := this.GetTokenSqlValue(m)
|
||||
|
||||
operator := contracts.ConditionOperator(strings.ToUpper(string(this.GetOperator())))
|
||||
|
||||
if value == "" {
|
||||
// @todo return true
|
||||
// value = "''"
|
||||
}
|
||||
|
||||
//
|
||||
secondary := ""
|
||||
switch operator {
|
||||
case contracts.ConditionOperator_IS_NULL:
|
||||
case contracts.ConditionOperator_IS_NOT_NULL:
|
||||
|
||||
secondary = ""
|
||||
case contracts.ConditionOperator_EQ, contracts.ConditionOperator_NE,
|
||||
contracts.ConditionOperator_GT, contracts.ConditionOperator_GE,
|
||||
contracts.ConditionOperator_LT, contracts.ConditionOperator_LE,
|
||||
contracts.ConditionOperator_REGEXP, contracts.ConditionOperator_NOT_REGEXP:
|
||||
|
||||
if this.GetTokenType() == contracts.ConditionTokenType_SQL {
|
||||
secondary = value
|
||||
} else {
|
||||
secondary = "'" + strings.Trim(value, "'") + "'"
|
||||
}
|
||||
|
||||
case contracts.ConditionOperator_LIKE, contracts.ConditionOperator_NOT_LIKE:
|
||||
secondary = "'%" + strings.Trim(value, "'") + "%'"
|
||||
case contracts.ConditionOperator_IN, contracts.ConditionOperator_NOT_IN:
|
||||
secondary = "(" + lo.Ternary(value == "", "''", value) + ")"
|
||||
}
|
||||
|
||||
if this.fieldSqlFunc == "json_member_of" {
|
||||
if this.fieldSqlFuncParam == "" {
|
||||
return db.Raw(fmt.Sprintf("JSON_CONTAINS(%s, JSON_ARRAY(%s))", secondary, first))
|
||||
// return db.Raw(fmt.Sprintf("%s MEMBER OF(%s)", secondary, first))
|
||||
} else {
|
||||
return db.Raw(fmt.Sprintf("JSON_CONTAINS(%s->>'%s', JSON_ARRAY(%s))", secondary, this.fieldSqlFuncParam, first))
|
||||
// return db.Raw(fmt.Sprintf("%s MEMBER OF(%s->'%s')", secondary, first, this.FieldSqlFuncParam))
|
||||
}
|
||||
} else if this.fieldSqlFunc == "json_contains" {
|
||||
if this.fieldSqlFuncParam == "" {
|
||||
return db.Raw(fmt.Sprintf("JSON_CONTAINS(%s, JSON_ARRAY(%s))", first, secondary))
|
||||
} else {
|
||||
return db.Raw(fmt.Sprintf("JSON_CONTAINS(%s->>'%s', JSON_ARRAY(%s))", first, this.fieldSqlFuncParam, secondary))
|
||||
}
|
||||
} else if this.fieldSqlFunc != "" && this.fieldSqlFuncParam != "" {
|
||||
first = this.fieldSqlFunc + "(" + first + ", " + this.fieldSqlFuncParam + ")"
|
||||
} else if this.fieldSqlFunc != "" {
|
||||
first = this.fieldSqlFunc + "(" + first + ")"
|
||||
}
|
||||
|
||||
return db.Raw(strings.Trim(first+" "+string(operator)+" "+secondary, " "))
|
||||
}
|
||||
|
||||
func (this ConditionExpr) GetTokenName() string {
|
||||
return this.token
|
||||
}
|
||||
|
||||
func (this ConditionExpr) GetTokenType() contracts.ConditionTokenType {
|
||||
return this.tokenType
|
||||
}
|
||||
|
||||
func (this *ConditionExpr) GetTokenSqlValue(m contracts.ModelParam) string {
|
||||
if this.GetTokenType() == contracts.ConditionTokenType_SQL {
|
||||
return this.token
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(this.GetTokenValue(m))
|
||||
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
rv = reflect.Indirect(rv)
|
||||
}
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.Invalid:
|
||||
return ""
|
||||
case reflect.Slice:
|
||||
aStr := cast.ToStringSlice(rv.Interface())
|
||||
|
||||
for i := 0; i < len(aStr); i++ {
|
||||
if aStr[i] != "" {
|
||||
aStr[i] = "'" + strings.Trim(db.MysqlRealEscapeString(aStr[i]), "'") + "'"
|
||||
}
|
||||
}
|
||||
|
||||
// 强制使用 in
|
||||
if this.operator == contracts.ConditionOperator_EQ {
|
||||
this.operator = contracts.ConditionOperator_IN
|
||||
}
|
||||
|
||||
return strings.Join(aStr, ", ")
|
||||
case reflect.Struct:
|
||||
b, _ := json.Marshal(rv.Interface())
|
||||
return fmt.Sprintf("'%s'", b)
|
||||
default:
|
||||
return db.MysqlRealEscapeString(fmt.Sprintf("%v", rv.Interface()))
|
||||
}
|
||||
}
|
||||
|
||||
func (this ConditionExpr) GetTokenValue(m contracts.ModelParam) any {
|
||||
switch this.GetTokenType() {
|
||||
case contracts.ConditionTokenType_PARAM:
|
||||
if this.matchPrefix != "" {
|
||||
return m.GetParam(fmt.Sprintf("%s.%s", this.matchPrefix, this.token)).Value()
|
||||
}
|
||||
return m.GetParam(this.token).Value()
|
||||
case contracts.ConditionTokenType_STRING:
|
||||
return this.token
|
||||
case contracts.ConditionTokenType_FUNC:
|
||||
switch this.token {
|
||||
case "UserID":
|
||||
return m.GetGlobalParamsUser().ID()
|
||||
case "UserUuid":
|
||||
return m.GetGlobalParamsUser().Uuid()
|
||||
case "UserRolesUuid":
|
||||
return m.GetGlobalParamsUser().Roles()
|
||||
case "UserPlatform":
|
||||
return m.GetGlobalParamsUser().Platform()
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this ConditionExpr) IsIgnoreEmptyParma(m contracts.ModelParam) bool {
|
||||
if !this.ignoreEmptyParma {
|
||||
return false
|
||||
}
|
||||
|
||||
if this.tokenType != contracts.ConditionTokenType_PARAM {
|
||||
return false
|
||||
}
|
||||
|
||||
param := this.GetTokenValue(m)
|
||||
|
||||
if param == "" || param == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func NewExpr(rResource, rField, token string, operator contracts.ConditionOperator, tType contracts.ConditionTokenType, ignoreEmptyParma bool, fn, fnParam string) contracts.ConditionExpr {
|
||||
return &ConditionExpr{
|
||||
operator: operator,
|
||||
field: rField,
|
||||
fieldResource: rResource,
|
||||
fieldSqlFunc: fn,
|
||||
fieldSqlFuncParam: fnParam,
|
||||
ignoreEmptyParma: ignoreEmptyParma,
|
||||
tokenType: tType,
|
||||
token: string(token),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user