yjp hai 1 ano
pai
achega
e5cbf5f1f0
Modificáronse 1 ficheiros con 114 adicións e 38 borrados
  1. 114 38
      convenient/domain/query_rule/query_rule_parser.go

+ 114 - 38
convenient/domain/query_rule/query_rule_parser.go

@@ -11,9 +11,23 @@ import (
 	"git.sxidc.com/go-tools/utils/strutils"
 	"github.com/pkg/errors"
 	"reflect"
+	"strings"
 )
 
+const (
+	LogicalOperatorAnd = "and"
+	LogicalOperatorOr  = "or"
+)
+
+func isSupportedLogicalOperator(logicalOperator string) bool {
+	return logicalOperator == LogicalOperatorAnd || logicalOperator == LogicalOperatorOr
+}
+
 type Rule struct {
+	LogicalOperator string `json:"logical_operator"`
+	Left            *Rule  `json:"left"`
+	Right           *Rule  `json:"right"`
+
 	FieldName  string `json:"fieldName"`
 	FieldType  string `json:"fieldType"`
 	ColumnName string `json:"columnName"`
@@ -22,6 +36,54 @@ type Rule struct {
 }
 
 func (r Rule) Check() error {
+	if strutils.IsStringNotEmpty(r.LogicalOperator) {
+		return r.checkAsNode()
+	} else {
+		return r.checkAsLeaf()
+	}
+}
+
+func (r Rule) checkAsNode() error {
+	if !isSupportedLogicalOperator(r.LogicalOperator) {
+		return errors.New("不支持的逻辑操作符")
+	}
+
+	if r.Left == nil {
+		return errors.New("左结点为空")
+	}
+
+	if r.Right == nil {
+		return errors.New("右结点为空")
+	}
+
+	if strutils.IsStringNotEmpty(r.Left.LogicalOperator) {
+		err := r.Left.checkAsNode()
+		if err != nil {
+			return err
+		}
+	} else {
+		err := r.Left.checkAsLeaf()
+		if err != nil {
+			return err
+		}
+	}
+
+	if strutils.IsStringNotEmpty(r.Right.LogicalOperator) {
+		err := r.Right.checkAsNode()
+		if err != nil {
+			return err
+		}
+	} else {
+		err := r.Right.checkAsLeaf()
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (r Rule) checkAsLeaf() error {
 	if strutils.IsStringEmpty(r.FieldName) {
 		return errors.New("字段名为空")
 	}
@@ -46,20 +108,13 @@ func (r Rule) Check() error {
 }
 
 func Lint(ruleStr string) error {
-	rules := make([]Rule, 0)
-	err := json.Unmarshal([]byte(ruleStr), &rules)
+	r := new(Rule)
+	err := json.Unmarshal([]byte(ruleStr), r)
 	if err != nil {
 		return err
 	}
 
-	for _, r := range rules {
-		err := r.Check()
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
+	return r.Check()
 }
 
 func HasRule(dbSchema string, scope string, domainName string, i *infrastructure.Infrastructure) (bool, error) {
@@ -71,7 +126,21 @@ func HasRule(dbSchema string, scope string, domainName string, i *infrastructure
 	})
 }
 
-func GetRules(dbSchema string, scope string, domainName string, i *infrastructure.Infrastructure) ([]Rule, error) {
+func GetRulesAndFormConditionClause(dbSchema string, scope string, domainName string, i *infrastructure.Infrastructure) (string, error) {
+	r, err := getRule(dbSchema, scope, domainName, i)
+	if err != nil {
+		return "", err
+	}
+
+	clause, err := formConditionClause(r)
+	if err != nil {
+		return "", err
+	}
+
+	return clause, nil
+}
+
+func getRule(dbSchema string, scope string, domainName string, i *infrastructure.Infrastructure) (Rule, error) {
 	dbExecutor := i.DBExecutor()
 
 	result, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{
@@ -79,25 +148,21 @@ func GetRules(dbSchema string, scope string, domainName string, i *infrastructur
 		Conditions: sql.NewConditions().Equal(ColumnScope, scope).Equal(ColumnDomainName, domainName),
 	})
 	if err != nil {
-		return nil, err
+		return Rule{}, err
 	}
 
-	rules := make([]Rule, 0)
-	err = json.Unmarshal([]byte(result.ColumnValueString(ColumnRule)), &rules)
+	r := new(Rule)
+	err = json.Unmarshal([]byte(result.ColumnValueString(ColumnRule)), r)
 	if err != nil {
-		return nil, err
+		return Rule{}, err
 	}
 
-	return rules, nil
+	return *r, nil
 }
 
-func FormConditions(rules []Rule) (*sql.Conditions, error) {
-	conditions := sql.NewConditions()
-	for _, r := range rules {
-		err := r.Check()
-		if err != nil {
-			return nil, err
-		}
+func formConditionClause(r Rule) (string, error) {
+	if strutils.IsStringEmpty(r.LogicalOperator) {
+		conditions := sql.NewConditions()
 
 		switch r.Operator {
 		case opEqual:
@@ -114,55 +179,66 @@ func FormConditions(rules []Rule) (*sql.Conditions, error) {
 			conditions.GreaterThanAndEqual(r.ColumnName, r.Value)
 		case opIn:
 			if reflect.TypeOf(r.Value).Kind() != reflect.Slice {
-				return nil, errors.New("使用\"包含在列表\"操作符必须使用列表")
+				return "", errors.New("使用\"包含在列表\"操作符必须使用列表")
 			}
 
 			conditions.In(r.FieldName, r.Value)
 		case opNotIn:
 			if reflect.TypeOf(r.Value).Kind() != reflect.Slice {
-				return nil, errors.New("使用\"不包含在列表\"操作符必须使用列表")
+				return "", errors.New("使用\"不包含在列表\"操作符必须使用列表")
 			}
 
 			conditions.NotIn(r.FieldName, r.Value)
 		case opPrefix:
 			strValue, err := reflectutils.ToString(r.Value)
 			if err != nil {
-				return nil, err
+				return "", err
 			}
 
 			conditions.Like(r.FieldName, strValue+"%")
 		case opSuffix:
 			strValue, err := reflectutils.ToString(r.Value)
 			if err != nil {
-				return nil, err
+				return "", err
 			}
 
 			conditions.Like(r.FieldName, "%"+strValue)
 		case opContains:
 			strValue, err := reflectutils.ToString(r.Value)
 			if err != nil {
-				return nil, err
+				return "", err
 			}
 
 			conditions.Like(r.FieldName, "%"+strValue+"%")
 		default:
-			return nil, errors.Errorf("不支持的操作符%v", r.Operator)
+			return "", errors.Errorf("不支持的操作符%v", r.Operator)
 		}
-	}
 
-	return conditions, nil
-}
+		return conditions.And(), nil
+	}
 
-func GetRulesAndFormConditions(dbSchema string, scope string, domainName string, i *infrastructure.Infrastructure) (*sql.Conditions, error) {
-	rules, err := GetRules(dbSchema, scope, domainName, i)
+	leftClause, err := formConditionClause(*r.Left)
 	if err != nil {
-		return nil, err
+		return "", err
 	}
 
-	conditions, err := FormConditions(rules)
+	rightClause, err := formConditionClause(*r.Right)
 	if err != nil {
-		return nil, err
+		return "", err
 	}
 
-	return conditions, nil
+	clauseBuilder := strings.Builder{}
+
+	clauseBuilder.WriteString("(" + leftClause + ")")
+
+	switch r.LogicalOperator {
+	case LogicalOperatorAnd:
+		clauseBuilder.WriteString(" AND ")
+	case LogicalOperatorOr:
+		clauseBuilder.WriteString(" OR ")
+	}
+
+	clauseBuilder.WriteString("(" + rightClause + ")")
+
+	return clauseBuilder.String(), nil
 }