package query_rule import ( "encoding/json" "git.sxidc.com/go-framework/baize/convenient/domain/query_rule/definition" "git.sxidc.com/go-framework/baize/convenient/domain/query_rule/rule" "git.sxidc.com/go-framework/baize/framework/binding" "git.sxidc.com/go-framework/baize/framework/core/api" "git.sxidc.com/go-framework/baize/framework/core/api/request" "git.sxidc.com/go-framework/baize/framework/core/api/response" "git.sxidc.com/go-framework/baize/framework/core/application" "git.sxidc.com/go-framework/baize/framework/core/domain" "git.sxidc.com/go-framework/baize/framework/core/domain/entity" "git.sxidc.com/go-framework/baize/framework/core/infrastructure" "git.sxidc.com/go-framework/baize/framework/core/infrastructure/database" "git.sxidc.com/go-framework/baize/framework/core/infrastructure/database/clause" "git.sxidc.com/go-framework/baize/framework/core/infrastructure/database/sql" "git.sxidc.com/go-tools/utils/strutils" "github.com/pkg/errors" ) // Simple Bind参数 type Simple struct { // schema Schema string // 关闭记录查询规则 DisableRecordRule bool } func (simple *Simple) bind(binder *binding.Binder) { (&definition.Simple{Schema: simple.Schema}).Bind(binder) if !simple.DisableRecordRule { (&rule.Simple{Schema: simple.Schema}).Bind(binder) } } func Bind(app *application.App, simple *Simple) { binder := binding.NewBinder(app.Api().ChooseRouter(api.RouterPrefix, ""), app.Infrastructure()) simple.bind(binder) } type QueryRuleParseJsonBody struct { Rule string `json:"rule" assign:"-"` } type AdvanceQueryParams interface { GetRuleConditions() (string, []any) GetPageNo() int GetPageSize() int } type BaseAdvanceQueryParams struct { RuleClause string `json:"ruleClause" assign:"-"` RuleClauseArgs []any `json:"ruleClauseArgs" assign:"-"` PageNo int `json:"pageNo" assign:"-"` PageSize int `json:"pageSize" assign:"-"` } func (queryParams *BaseAdvanceQueryParams) GetRuleConditions() (string, []any) { return queryParams.RuleClause, queryParams.RuleClauseArgs } func (queryParams *BaseAdvanceQueryParams) GetPageNo() int { return queryParams.PageNo } func (queryParams *BaseAdvanceQueryParams) GetPageSize() int { return queryParams.PageSize } type FormAdditionalSelectClausesFunc func(queryParams AdvanceQueryParams) ([]string, error) type FormAdditionalFromFunc func(queryParams AdvanceQueryParams) ([]clause.Clause, error) type FormAdditionalConditionsFunc func(queryParams AdvanceQueryParams) (clause.Clause, error) type FormOtherClausesFunc func(queryParams AdvanceQueryParams) ([]clause.Clause, error) type AddUseQueryRuleQueryRouteParams struct { DBSchema string QueryParams AdvanceQueryParams FormAdditionalSelectClausesFunc FormAdditionalSelectClausesFunc FormAdditionalFromFunc FormAdditionalFromFunc FormAdditionalConditionsFunc FormAdditionalConditionsFunc FormOtherClausesFunc FormOtherClausesFunc Object domain.Object QueryMiddlewares []binding.Middleware } func (params *AddUseQueryRuleQueryRouteParams) check() error { if params.DBSchema == "" { return errors.New("没有传递DBSchema") } if params.Object == nil { return errors.New("没有传递Object") } return nil } func AddUseQueryRuleQueryRoute[O any](binder *binding.Binder, addParams *AddUseQueryRuleQueryRouteParams) error { err := addParams.check() if err != nil { return err } domainPath := domain.RelativeDomainPath(addParams.Object) var queryParams AdvanceQueryParams queryParams = new(BaseAdvanceQueryParams) if addParams.QueryParams != nil { queryParams = addParams.QueryParams } binding.PostBind(binder, &binding.SimpleBindItem[response.InfosData[O]]{ Path: domainPath + "/advancedQuery", SendResponseFunc: response.SendInfosResponse[O], RequestParams: queryParams, Objects: []domain.Object{addParams.Object}, ServiceFunc: func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (response.InfosData[O], error) { errResponse := response.InfosData[O]{ Infos: make([]O, 0), } if params == nil { return errResponse, errors.New("请求参数为空") } object := objects[0] if object == nil { return errResponse, errors.New("领域实体为空") } advanceQueryParams, ok := params.(AdvanceQueryParams) if !ok { return errResponse, errors.New("请求参数不是Query接口") } e, ok := objects[0].(entity.Entity) if !ok { return errResponse, errors.New("需要传递领域对象应该为实体") } var selectClause *clause.Select var countClause *clause.Select var fromClause *clause.From var additionalConditions clause.Clause selectClauses := make([]string, 0) fromClauses := []clause.Clause{clause.TableName(domain.TableName(addParams.DBSchema, e))} selectOtherClauses := make([]clause.Clause, 0) countOtherClauses := make([]clause.Clause, 0) if addParams.FormAdditionalSelectClausesFunc != nil { additionalSelectClauses, err := addParams.FormAdditionalSelectClausesFunc(advanceQueryParams) if err != nil { return errResponse, err } selectClauses = additionalSelectClauses } if addParams.FormAdditionalFromFunc != nil { additionalFromClauses, err := addParams.FormAdditionalFromFunc(advanceQueryParams) if err != nil { return errResponse, err } fromClauses = append(fromClauses, additionalFromClauses...) } fromClause = clause.NewFrom(fromClauses) limitClause := clause.NewLimit(advanceQueryParams.GetPageNo(), advanceQueryParams.GetPageSize()) if addParams.FormAdditionalConditionsFunc != nil { conditions, err := addParams.FormAdditionalConditionsFunc(advanceQueryParams) if err != nil { return errResponse, err } additionalConditions = conditions } ruleClause, ruleClauseArgs := advanceQueryParams.GetRuleConditions() if strutils.IsStringEmpty(ruleClause) { if additionalConditions != nil { selectOtherClauses = append(selectOtherClauses, clause.NewWhere(additionalConditions), limitClause) countOtherClauses = append(countOtherClauses, clause.NewWhere(additionalConditions)) } else { selectOtherClauses = append(selectOtherClauses, limitClause) } } else { var conditionClause clause.Clause conditionClause = clause.NewConditions().AddCondition(ruleClause, ruleClauseArgs...).And() if additionalConditions != nil { conditionClause = clause.NewConditionJoin(conditionClause, additionalConditions).And() } selectOtherClauses = append(selectOtherClauses, clause.NewWhere(conditionClause), limitClause) countOtherClauses = append(countOtherClauses, clause.NewWhere(conditionClause)) } if addParams.FormOtherClausesFunc != nil { otherClauses, err := addParams.FormOtherClausesFunc(advanceQueryParams) if err != nil { return errResponse, err } selectOtherClauses = append(selectOtherClauses, otherClauses...) countOtherClauses = append(countOtherClauses, otherClauses...) } selectClause = clause.NewSelect(selectClauses, fromClause, selectOtherClauses...) countClause = clause.NewSelect([]string{"COUNT(*) AS total"}, fromClause, countOtherClauses...) selectClauseStr, err := selectClause.Clause() if err != nil { return errResponse, err } results, err := database.ExecuteRawSql(i.DBExecutor(), selectClauseStr, selectClause.Args()...) if err != nil { return errResponse, err } countClauseStr, err := countClause.Clause() if err != nil { return errResponse, err } countResults, err := database.ExecuteRawSql(i.DBExecutor(), countClauseStr, countClause.Args()...) if err != nil { return errResponse, err } infos := make([]O, 0) err = sql.ParseSqlResult(results, &infos) if err != nil { return errResponse, err } return response.InfosData[O]{ Infos: infos, TotalCount: countResults[0].ColumnValueInt64("total"), PageNo: advanceQueryParams.GetPageNo(), }, nil }, }, addParams.QueryMiddlewares...) binding.PostBind(binder, &binding.SimpleBindItem[map[string]any]{ Path: domainPath + "/queryRule/parse", SendResponseFunc: response.SendMapResponse, RequestParams: &QueryRuleParseJsonBody{}, ServiceFunc: func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (map[string]any, error) { errResponse := map[string]any{ "ruleClause": "", "ruleClauseArgs": make([]any, 0), } jsonBody, err := request.ToConcrete[*QueryRuleParseJsonBody](params) if err != nil { return errResponse, err } r := new(rule.Rule) err = json.Unmarshal([]byte(jsonBody.Rule), r) if err != nil { return errResponse, err } ruleConditionClause, err := rule.FormConditionClauseByRule(addParams.Object.DomainCamelName(), *r, nil) if err != nil { return errResponse, err } ruleConditionClauseStr, err := ruleConditionClause.Clause() if err != nil { return errResponse, err } return map[string]any{ "ruleClause": ruleConditionClauseStr, "ruleClauseArgs": ruleConditionClause.Args(), }, nil }, }) return nil }