作者 yangfu

feat: branch formula

package query
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"reflect"
"strings"
"github.com/beego/beego/v2/core/validation"
)
type CalculateItemPreviewQuery struct {
// 查询集合ID
QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
// 公式
Formula *domain.FieldExpr `json:"formula"`
}
func (dependencyGraphQuery *CalculateItemPreviewQuery) Valid(validation *validation.Validation) {
//validation.SetError("CustomValid", "未实现的自定义认证")
}
func (dependencyGraphQuery *CalculateItemPreviewQuery) ValidateQuery() error {
valid := validation.Validation{}
b, err := valid.Valid(dependencyGraphQuery)
if err != nil {
return err
}
if !b {
elem := reflect.TypeOf(dependencyGraphQuery).Elem()
for _, validErr := range valid.Errors {
field, isExist := elem.FieldByName(validErr.Field)
if isExist {
return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
} else {
return fmt.Errorf(validErr.Message)
}
}
}
return nil
}
... ...
... ... @@ -10,12 +10,13 @@ import (
)
type SearchQuerySetQuery struct {
Type string `cname:"类型" json:"type" valid:"Required"`
Flag string `cname:"标识" json:"flag"`
Status int `cname:"状态 1:启用 2:关闭" json:"status"`
MatchName string `cname:"匹配名称" json:"matchName"`
SortByName string `json:"sortByName"`
SortByTime string `json:"sortByTime"`
Type string `cname:"类型" json:"type"`
Types []string `cname:"类型" json:"types"`
Flag string `cname:"标识" json:"flag"`
Status int `cname:"状态 1:启用 2:关闭" json:"status"`
MatchName string `cname:"匹配名称" json:"matchName"`
SortByName string `json:"sortByName"`
SortByTime string `json:"sortByTime"`
}
func (searchQuerySetQuery *SearchQuerySetQuery) Valid(validation *validation.Validation) {
... ...
package service
import (
"fmt"
"github.com/linmadan/egglib-go/core/application"
"github.com/linmadan/egglib-go/utils/tool_funs"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
... ... @@ -9,7 +10,10 @@ import (
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/querySet/query"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/utils"
"time"
)
// 查询集合服务
... ... @@ -373,6 +377,108 @@ func (querySetService *QuerySetService) PreviewPrepare(ctx *domain.Context, upda
}, nil
}
func (querySetService *QuerySetService) CalculateItemPreview(ctx *domain.Context, q *query.CalculateItemPreviewQuery) (interface{}, error) {
if err := q.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
_, result := GetItemValues(transactionContext, q)
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return map[string]interface{}{
"itemValues": result,
}, nil
}
func (querySetService *QuerySetService) CalculateItemExport(ctx *domain.Context, q *query.CalculateItemPreviewQuery) (interface{}, error) {
if err := q.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
querySet, result := GetItemValues(transactionContext, q)
if querySet == nil {
return nil, err
}
var fields = make([]string, 0)
var values = make([]string, 0)
for _, f := range result {
fields = append(fields, f.Name)
values = append(values, f.Value)
}
filename := fmt.Sprintf("%v_%v.xlsx", querySet.Name, time.Now().Format("060102150405"))
path := fmt.Sprintf("public/%v", filename)
excelWriter := excel.NewXLXSWriterTo(fields, [][]string{values})
if err = excelWriter.Save(path); err != nil {
return nil, factory.FastError(err)
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return map[string]interface{}{
"url": domain.DownloadUrl(filename),
}, err
}
func GetItemValues(transactionContext application.TransactionContext, q *query.CalculateItemPreviewQuery) (*domain.QuerySet, []itemValue) {
_, querySet, err := factory.FastPgQuerySet(transactionContext, q.QuerySetId)
if err != nil {
return nil, nil
}
value := starrocks.CalculateItemValue(starrocks.DB, q.Formula)
var result = make([]itemValue, 0)
result = append(result, itemValue{
Name: querySet.Name,
Value: value,
})
for _, f := range q.Formula.TableFields {
_, table, _ := factory.FastPgTable(transactionContext, f.TableId)
if table == nil {
continue
}
if table.TableType != domain.CalculateItem.ToString() {
continue
}
value := starrocks.CalculateItemValue(starrocks.DB, &domain.FieldExpr{
TableFields: []domain.TableField{f},
ExprSql: f.FieldSqlName,
})
result = append(result, itemValue{
Name: f.FieldName,
Value: value,
})
}
return querySet, result
}
type itemValue struct {
Name string `json:"name"`
Value string `json:"value"`
}
func NewQuerySetService(options map[string]interface{}) *QuerySetService {
newQuerySetService := &QuerySetService{}
return newQuerySetService
... ...
... ... @@ -19,6 +19,8 @@ type TableDto struct {
ParentId int `json:"parentId"`
// 模块 应用于模块 1:数控中心 2:拆解模块 4:计算模块
Module int `json:"module"`
// 标识
Flag string `json:"flag,omitempty"`
// 表字段
Fields []*domain.Field `json:"fields"`
}
... ...
package dto
import (
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
)
type TableObjectDto struct {
// 序号
Id int `json:"id"`
// 表Id
TableId int `json:"tableId"`
// 表类型 MainTable:主表 SideTable:副表 SubTable:分表 ExcelTable:Excel表
TableType string `json:"tableType"`
// 名称
Name string `json:"name"`
// 对应数据库名称
SQLName string `json:"sqlName,omitempty"`
// 父级ID
ParentId int `json:"parentId"`
// 模块 应用于模块 1:数控中心 2:拆解模块 4:计算模块
//Module int `json:"module"`
// 标识
Flag string `json:"flag,omitempty"`
// 启用状态
Status int `json:"status"`
// 表字段
Fields []*domain.Field `json:"fields"`
}
func (d *TableObjectDto) Load(m *domain.Table) *TableObjectDto {
d.Id = m.TableId
d.TableId = m.TableId
d.TableType = m.TableType
d.Name = m.Name
d.ParentId = m.ParentId
d.SQLName = m.SQLName
//if m.TableInfo != nil {
// d.Module = m.TableInfo.ApplyOnModule
//}
d.Fields = make([]*domain.Field, 0)
return d
}
func (d *TableObjectDto) LoadGroup(m *domain.QuerySet) *TableObjectDto {
d.Id = m.QuerySetId
d.TableId = 0
d.TableType = m.Type
d.Name = m.Name
d.ParentId = m.ParentId
//if m.TableInfo != nil {
// d.Module = m.TableInfo.ApplyOnModule
//}
d.Status = m.Status
d.Flag = m.Flag
d.Fields = make([]*domain.Field, 0)
return d
}
func (d *TableObjectDto) Update(m *domain.QuerySet) *TableObjectDto {
d.Id = m.QuerySetId
d.Flag = m.Flag
d.Status = m.Status
d.ParentId = m.ParentId
return d
}
func (d *TableObjectDto) SetDetailStructInfo(m *domain.Table) *TableObjectDto {
d.Fields = append(d.Fields, m.DataFields...)
d.Fields = append(d.Fields, m.ManualFields...)
d.SQLName = m.SQLName
return d
}
... ...
... ... @@ -11,18 +11,28 @@ import (
type SearchTableQuery struct {
// 表名称
Name string `cname:"表名称" json:"name"`
ViewType string `cname:"视图类型 full:完整 main:主表关系" json:"viewType"`
Name string `cname:"表名称" json:"name"`
//ViewType string `cname:"视图类型 full:完整 main:主表关系" json:"viewType"`
// 表类型 MainTable:主表 SideTable:副表 SubTable:分表 ExcelTable:Excel表 SubProcess:子过程 Schema:方案
TableTypes []string `cname:"表类型 MainTable:主表 SideTable:副表 SubTable:分表 ExcelTable:Excel表" json:"tableTypes"`
TableTypes []string `cname:"表类型 MainTable:主表 SideTable:副表 SubTable:分表 ExcelTable:Excel表" json:"tableTypes" valid:"Required"`
// 父级ID
ParentId int `cname:"父级ID" json:"parentId"`
// 模块 应用于模块 1:数控中心 2:拆解模块 4:计算模块
Module int `json:"module"`
// 父级ID
ParentTableId int `cname:"父级ID" json:"parentTableId"`
ReturnDetailStructInfo bool `cname:"返回具体的结构信息 默认不返回" json:"ReturnDetailStructInfo"`
Context *domain.Context
ParentTableId int `cname:"父级ID" json:"parentTableId"`
// 返回结构信息
ReturnDetailStructInfo bool `cname:"返回具体的结构信息 默认不返回" json:"returnDetailStructInfo"`
// 排除分组项,只返回一级列表;默认 false 不排除,连分组也返回
ReturnGroupItem bool `cname:"排除分组" json:"returnGroupItem"`
Context *domain.Context
FilterRules []*FilterRule `json:"filterRules"`
TableId int `cname:"ID" json:"tableId"`
}
type FilterRule struct {
// *:匹配所有
TableType string `json:"tableType"`
Status int `json:"status"`
}
func (searchQuery *SearchTableQuery) Valid(validation *validation.Validation) {
... ...
package query
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"reflect"
"strings"
"github.com/beego/beego/v2/core/validation"
)
type SearchTableRelationGraphQuery struct {
// 表名称
Name string `cname:"表名称" json:"name"`
ViewType string `cname:"视图类型 full:完整 main:主表关系" json:"viewType"`
// 表类型 MainTable:主表 SideTable:副表 SubTable:分表 ExcelTable:Excel表 SubProcess:子过程 Schema:方案
TableTypes []string `cname:"表类型 MainTable:主表 SideTable:副表 SubTable:分表 ExcelTable:Excel表" json:"tableTypes"`
// 父级ID
ParentId int `cname:"父级ID" json:"parentId"`
// 模块 应用于模块 1:数控中心 2:拆解模块 4:计算模块
Module int `json:"module"`
// 父级ID
ParentTableId int `cname:"父级ID" json:"parentTableId"`
ReturnDetailStructInfo bool `cname:"返回具体的结构信息 默认不返回" json:"returnDetailStructInfo"`
Context *domain.Context
}
func (searchQuery *SearchTableRelationGraphQuery) Valid(validation *validation.Validation) {
if searchQuery.ParentTableId > 0 && searchQuery.ParentId == 0 {
searchQuery.ParentId = searchQuery.ParentTableId
}
}
func (searchQuery *SearchTableRelationGraphQuery) ValidateQuery() error {
valid := validation.Validation{}
b, err := valid.Valid(searchQuery)
if err != nil {
return err
}
if !b {
elem := reflect.TypeOf(searchQuery).Elem()
for _, validErr := range valid.Errors {
field, isExist := elem.FieldByName(validErr.Field)
if isExist {
return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
} else {
return fmt.Errorf(validErr.Message)
}
}
}
return nil
}
... ...
... ... @@ -249,7 +249,7 @@ func (tableService *TableService) Search(searchQuery *query.SearchTableQuery) (i
}
// 表搜索
func (tableService *TableService) RelationGraph(searchQuery *query.SearchTableQuery) (interface{}, error) {
func (tableService *TableService) RelationGraph(searchQuery *query.SearchTableRelationGraphQuery) (interface{}, error) {
if err := searchQuery.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
... ... @@ -436,6 +436,9 @@ func (tableService *TableService) ValidExprSql(ctx *domain.Context, cmd *command
//if _, parseErr := strconv.ParseFloat(cmd.ExprSql, 64); parseErr != nil {
// selectValue = "'" + selectValue + "'"
//}
if len(cmd.ExprSql) == 0 {
selectValue = "''"
}
sql := "select " + selectValue + " as expr"
if len(set.KeysStr()) > 0 {
sql += " from " + strings.Join(set.KeysStr(), ",")
... ...
package service
import (
"fmt"
"github.com/linmadan/egglib-go/core/application"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/dto"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/query"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/utils"
"sort"
)
func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTableQuery) (interface{}, error) {
if err := searchQuery.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
tableRepository, _, _ := factory.FastPgTable(transactionContext, 0)
_, tables, err := tableRepository.Find(utils.ObjectToMap(searchQuery))
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
var result = make([]*dto.TableObjectDto, 0)
for _, table := range tables {
var item = &dto.TableObjectDto{}
item.Load(table)
if searchQuery.ReturnDetailStructInfo {
item.SetDetailStructInfo(table)
}
item.Flag = domain.FlagSet
if item.TableType == domain.MainTable.ToString() || item.TableType == domain.SubTable.ToString() || item.TableType == domain.SideTable.ToString() {
item.ParentId = 0
item.Status = domain.StatusOn
}
result = append(result, item)
}
if searchQuery.TableId > 0 {
return map[string]interface{}{
"count": len(result),
"tableObjects": result,
}, nil
}
querySetRepository, _, _ := factory.FastPgQuerySet(transactionContext, 0)
_, querySets, _ := querySetRepository.Find(map[string]interface{}{"context": searchQuery.Context})
if !searchQuery.ReturnGroupItem {
querySets = make([]*domain.QuerySet, 0)
}
// BindTableId , parentId
querySetMapByTableId := make(map[int]*domain.QuerySet)
for _, qs := range querySets {
if qs.QuerySetInfo.BindTableId == 0 {
continue
}
querySetMapByTableId[qs.QuerySetInfo.BindTableId] = qs
}
querySetMapById := make(map[int]*domain.QuerySet)
for _, qs := range querySets {
querySetMapById[qs.QuerySetId] = qs
}
var response = make([]*dto.TableObjectDto, 0)
// 分组
querySetMapGroup := make(map[int]bool)
querySetGroups := make([]*domain.QuerySet, 0)
for _, t := range result {
if !domain.TableType(t.TableType).TableHasGroup() {
response = append(response, t)
continue
}
v, ok := querySetMapByTableId[t.TableId]
if !ok {
response = append(response, t)
continue
}
t.Update(v)
parentGroupId := v.ParentId
if filterTableByFilterRule(t, searchQuery.FilterRules) {
continue
}
response = append(response, t)
for {
if parentGroupId == 0 {
break
}
if _, ok := querySetMapGroup[parentGroupId]; ok {
break
}
querySetMapGroup[parentGroupId] = true
if v, ok := querySetMapById[parentGroupId]; ok {
querySetGroups = append(querySetGroups, v)
parentGroupId = v.ParentId
}
}
}
for _, querySetGroup := range querySetGroups {
var groupItem = &dto.TableObjectDto{}
groupItem.LoadGroup(querySetGroup)
response = append(response, groupItem)
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
sort.Slice(response, func(i, j int) bool {
item1 := response[i]
item2 := response[j]
k1 := fmt.Sprintf("%v-%v-%v", item1.TableType, item1.ParentId, item1.Id)
k2 := fmt.Sprintf("%v-%v-%v", item2.TableType, item2.ParentId, item2.Id)
return k1 < k2
})
return map[string]interface{}{
"count": len(response),
"tableObjects": response,
}, nil
}
// true:代表需要过滤 false:不需要过滤
func filterTableByFilterRule(item *dto.TableObjectDto, filterRules []*query.FilterRule) bool {
for _, rule := range filterRules {
if rule.TableType == item.TableType && rule.Status > 0 && rule.Status != item.Status {
return true
}
if rule.TableType == item.TableType && rule.Status == 0 {
return true
}
}
for _, rule := range filterRules {
if rule.TableType == "*" && rule.Status > 0 && rule.Status != item.Status {
return true
}
//if rule.TableType == rule.TableType && rule.Status > 0 && rule.Status != item.Status {
// return true
//}
}
return false
}
... ...
... ... @@ -34,6 +34,12 @@ var (
RenameQuerySet OperationType = "RenameQuerySet" // 重命名
DeleteQuerySet OperationType = "DeleteQuerySet" // 删除
CreateFormula OperationType = "CreateFormula" // 新增公式
DeleteFormula OperationType = "DeleteFormula" // 删除公式
EditCalculateItem OperationType = "EditCalculateItem" // 编辑公式
EditCalculateTable OperationType = "EditCalculateTable" // 编辑计算表
EditCalculateSet OperationType = "EditCalculateSet" // 编辑计算集
UnKnown OperationType = "UnKnown" // 未知
)
... ... @@ -60,12 +66,19 @@ var OperationTypeMap = map[string]string{
CopyQuerySet.ToString(): "复制",
RenameQuerySet.ToString(): "重命名",
DeleteQuerySet.ToString(): "删除",
CreateFormula.ToString(): "新增公式",
DeleteFormula.ToString(): "删除公式",
EditCalculateItem.ToString(): "编辑公式",
EditCalculateTable.ToString(): "编辑计算表",
EditCalculateSet.ToString(): "编辑计算集",
}
var (
VerifiedStepLog LogType = "VerifiedStepLog"
CommonLog LogType = "CommonLog"
QuerySetLog LogType = "QuerySetLog"
FormulaLog LogType = "FormulaLog"
)
var (
... ... @@ -97,6 +110,8 @@ var ObjectTypeMap = map[string]string{
ObjectDBTable: "业务表",
SchemaTable.ToString(): "方案",
SubProcessTable.ToString(): "子过程",
CalculateItem.ToString(): "计算项",
CalculateTable.ToString(): "计算表",
}
var (
... ... @@ -140,6 +155,14 @@ func (t TableType) ToString() string {
return string(t)
}
func (t TableType) TableStatusEditable() bool {
return t == SchemaTable || t == CalculateItem || t == CalculateTable || t == CalculateSet
}
func (t TableType) TableHasGroup() bool {
return t == SchemaTable || t == SubProcessTable || t == CalculateItem || t == CalculateTable || t == CalculateSet
}
type ObjectType TableType
type OperationType string
... ... @@ -295,6 +318,64 @@ var DBTables = map[int]*Table{
},
},
},
DBTableFormulaLog.ToInt(): &Table{
TableId: 3,
TableType: ObjectDBTable,
Name: "日志信息",
SQLName: "metadata.logs",
DataFieldIndex: 6,
PK: &Field{
Index: 0,
Name: "日志ID",
SQLName: "log_id",
SQLType: Int.ToString(),
Flag: PKField,
},
DataFields: []*Field{
{
Index: 1,
Name: "公式名称",
SQLName: "object_name",
SQLType: String.ToString(),
Flag: MainTableField,
},
{
Index: 2,
Name: "类型",
SQLName: "object_type",
SQLType: String.ToString(),
Flag: MainTableField,
},
{
Index: 3,
Name: "操作类型",
SQLName: "operation_type",
SQLType: String.ToString(),
Flag: MainTableField,
},
{
Index: 4,
Name: "日志内容",
SQLName: "content",
SQLType: String.ToString(),
Flag: MainTableField,
},
{
Index: 5,
Name: "操作时间",
SQLName: "log_time", //"created_at",
SQLType: String.ToString(),
Flag: MainTableField,
},
{
Index: 6,
Name: "操作人",
SQLName: "operator_name",
SQLType: String.ToString(),
Flag: MainTableField,
},
},
},
}
type DBTable int
... ... @@ -306,6 +387,7 @@ func (t DBTable) ToInt() int {
const (
DBTableTableOperateLog DBTable = 1
DBTableQuerySetLog DBTable = 2
DBTableFormulaLog DBTable = 3
)
const (
... ...
... ... @@ -23,6 +23,8 @@ type Field struct {
Description string `json:"description"`
// 标识 1.主键 2:主表字段 3:手动添加
Flag int `json:"flag"`
// 排序
Order string `json:"order,omitempty"`
}
func (f *Field) Valid() error {
... ...
... ... @@ -21,6 +21,7 @@ type LogEntry struct {
// 错误信息
Error string `json:"error"`
ctx *Context `json:"-"`
Type string `json:"-"`
}
func (l LogEntry) Entry() LogEntry {
... ... @@ -31,6 +32,10 @@ func (l LogEntry) Context() *Context {
return l.ctx
}
func (l LogEntry) LogType() string {
return l.Type
}
func (l LogEntry) OperateType() string {
return l.OperationType
}
... ...
... ... @@ -82,7 +82,11 @@ func (querySet *QuerySet) Update(queryComponents []*QueryComponent, tableId int)
}
func ValidQuerySetType(t string) error {
if t == SchemaTable.ToString() || t == SubProcessTable.ToString() {
if t == SchemaTable.ToString() ||
t == SubProcessTable.ToString() ||
t == CalculateItem.ToString() ||
t == CalculateTable.ToString() ||
t == CalculateSet.ToString() {
return nil
}
return fmt.Errorf("类型有误")
... ... @@ -99,7 +103,9 @@ func (querySet *QuerySet) GetDependencyTables(queryComponents []*QueryComponent)
set := collection.NewSet()
for i := range queryComponents {
set.AddInt(queryComponents[i].MasterTable.TableId)
if queryComponents[i].MasterTable != nil && queryComponents[i].MasterTable.TableId > 0 {
set.AddInt(queryComponents[i].MasterTable.TableId)
}
for _, c := range queryComponents[i].Conditions {
for _, f := range c.FieldLeft.TableFields {
set.AddInt(f.TableId)
... ... @@ -116,6 +122,11 @@ func (querySet *QuerySet) GetDependencyTables(queryComponents []*QueryComponent)
set.AddInt(f.TableId)
}
}
if queryComponents[i].Formula != nil {
for _, f := range queryComponents[i].Formula.TableFields {
set.AddInt(f.TableId)
}
}
}
res := set.KeysInt()
sort.Ints(res)
... ...
... ... @@ -3,8 +3,11 @@ package domain
import "fmt"
var (
SchemaTable TableType = "Schema"
SubProcessTable TableType = "SubProcess"
SchemaTable TableType = "Schema" // 方案
SubProcessTable TableType = "SubProcess" // 子过程
CalculateItem TableType = "CalculateItem" // 计算项
CalculateTable TableType = "CalculateTable" // 计算表
CalculateSet TableType = "CalculateSet" // 计算集
)
var (
... ... @@ -21,13 +24,13 @@ var (
type SelectExprType string
type QueryComponent struct {
Id string `json:"id"`
MasterTable QueryComponentTable `json:"masterTable"`
Conditions []ConditionExpr `json:"conditions"`
JoinTables []QueryComponentTable `json:"-"` //joinTables
Selects []SelectExprGroup `json:"selects"`
SelectFromTables []QueryComponentTable `json:"-"` //selectTables
Description string `json:"description"`
Id string `json:"id"`
MasterTable *QueryComponentTable `json:"masterTable"`
Conditions []ConditionExpr `json:"conditions"`
Selects []SelectExprGroup `json:"selects"`
Description string `json:"description"`
Formula *FieldFormulaExpr `json:"formula"`
Aggregation *AggregationRule `json:"aggregation"`
}
func (qc QueryComponent) AllSelectExpr() []SelectExpr {
... ... @@ -59,6 +62,10 @@ func (c ConditionExpr) ExprHuman() string {
return c.FieldLeft.ExprHuman + c.OperatorSymbol + c.FieldRight.ExprHuman
}
type FieldFormulaExpr struct {
FieldExpr
}
type SelectExpr struct { // 查询表达式
Id string `json:"id"`
FieldLeft FieldExpr `json:"fieldLeft"`
... ... @@ -129,8 +136,8 @@ type Join struct {
On SelectExpr
}
func NewQueryComponentTable(t *Table) QueryComponentTable {
return QueryComponentTable{
func NewQueryComponentTable(t *Table) *QueryComponentTable {
return &QueryComponentTable{
TableId: t.TableId,
TableType: t.TableType,
Name: t.Name,
... ...
package domain
import (
"bytes"
"fmt"
)
type AggregationRule struct {
Aggregation
}
type Aggregation struct {
// 行
RowFields []*AggregationField `json:"rowFields"`
// 值
ValueFields []*AggregationField `json:"valueFields"`
// 选择列表 【字段名称】
SelectFields []string `json:"selectFields"`
}
type AggregationField struct {
Id string `json:"id"`
Field *Field `json:"field"`
DisplayName string `json:"displayName"`
AggregationFlag string `json:"aggregationFlag"` // 行:row 列:column 值:value
Order string `json:"order"` // 降序:desc 升序asc 默认:"" 无排序
Expr FieldExpr `json:"expr"`
}
func (ar *AggregationRule) Fields() []*Field {
fields := make([]*Field, 0)
for _, f := range ar.RowFields {
fields = append(fields, f.Field)
}
for _, f := range ar.ValueFields {
fields = append(fields, f.Field)
}
return fields
}
func (ar *AggregationRule) AggregationFields() []*AggregationField {
fields := make([]*AggregationField, 0)
for _, f := range ar.RowFields {
fields = append(fields, f)
}
for _, f := range ar.ValueFields {
fields = append(fields, f)
}
return fields
}
func (ar *AggregationRule) OrderFields() []*Field {
aggregationFields := ar.AggregationFields()
var fields = make([]*Field, 0)
for _, f := range aggregationFields {
if f.Order != "" {
copyField := f.Field.Copy()
copyField.Order = f.Order
fields = append(fields, copyField)
}
}
return fields
}
func (ar *AggregationField) Diff(c *AggregationField) bool {
if ar.Expr.ExprSql != c.Expr.ExprSql {
return true
}
if ar.Order != c.Order {
return true
}
if ar.AggregationFlag != c.AggregationFlag {
return true
}
return false
}
func (ar *AggregationField) Info() string {
buf := bytes.NewBuffer(nil)
buf.WriteString("(")
buf.WriteString(fmt.Sprintf("%s|", ar.DisplayName))
buf.WriteString(fmt.Sprintf("%s,", ar.Expr.ExprHuman))
if ar.AggregationFlag == "row" {
buf.WriteString("分组,")
} else {
buf.WriteString("不分组,")
}
if ar.Order == "asc" {
buf.WriteString("升序")
} else if ar.Order == "desc" {
buf.WriteString("降序")
} else {
buf.WriteString("默认")
}
buf.WriteString(")")
return buf.String()
}
... ...
... ... @@ -27,6 +27,8 @@ type Table struct {
DataFields []*Field `json:"dataFields"`
// 手动添加的列
ManualFields []*Field `json:"manualFields"`
// 默认排序列
//OrderFields []*Field `json:"orderFields"`
// 创建时间
CreatedAt time.Time `json:"createdAt"`
// 更新时间
... ...
... ... @@ -104,7 +104,7 @@ func NewFormulaCondition(queryComponent *domain.QueryComponent) FormulaCondition
return res
}
func NewFormulaSelectFields(t domain.QueryComponentTable) FormulaSelectFields {
func NewFormulaSelectFields(t *domain.QueryComponentTable) FormulaSelectFields {
var res = FormulaSelectFields{
DatabaseTableName: t.SQLName,
FieldSchemas: ToFieldSchemas(t.Fields),
... ...
... ... @@ -7,6 +7,7 @@ import (
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/bytelib"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks"
)
type ByteCoreService struct {
... ... @@ -128,6 +129,24 @@ func (ptr *ByteCoreService) FieldOptionalValues(param domain.ReqFieldOptionalVal
func (ptr *ByteCoreService) FormulasGenerate(param domain.ReqFormulasGenerate) (*domain.DataFormulasGenerate, error) {
apiByteLib := bytelib.NewApiByteLib(constant.BYTE_CORE_HOST)
if param.QuerySet.Type == domain.CalculateItem.ToString() {
if err := starrocks.Exec(starrocks.DB,
starrocks.CreateViewSql(param.Table.SQLName, param.Table.DataFields,
starrocks.CalculateItemViewSql(&param.QueryComponents[0].Formula.FieldExpr),
)); err != nil {
return nil, err
}
return &domain.DataFormulasGenerate{}, nil
}
if param.QuerySet.Type == domain.CalculateTable.ToString() {
if err := starrocks.Exec(starrocks.DB,
starrocks.CreateViewSql(param.Table.SQLName, param.Table.DataFields,
starrocks.CalculateTableViewSql(param.QueryComponents[0].MasterTable.SQLName, &param.QueryComponents[0].Aggregation.Aggregation),
)); err != nil {
return nil, err
}
return &domain.DataFormulasGenerate{}, nil
}
return apiByteLib.FormulasGenerate(param)
}
... ...
... ... @@ -137,6 +137,9 @@ func NewTable(tableType domain.TableType, fileName string, dataFields []*domain.
table.Name = fileName
table.SQLName = pin(fileName) //SQLTableName()
table.PK = PK()
if table.TableType == domain.CalculateTable.ToString() || table.TableType == domain.CalculateItem.ToString() {
table.PK = nil
}
table.DataFieldIndex = len(dataFields)
for i, field := range dataFields {
table.DataFields = append(table.DataFields, DataField(field.Name, field.SQLType, domain.MainTableField, i+1))
... ... @@ -156,6 +159,9 @@ func NewCopyTable(tableType domain.TableType, fileName string, dataFields []*dom
table.Name = fileName
table.SQLName = pin(fileName) //SQLTableName()
table.PK = PK()
if table.TableType == domain.CalculateTable.ToString() || table.TableType == domain.CalculateItem.ToString() {
table.PK = nil
}
table.DataFieldIndex = len(dataFields)
table.DataFields = dataFields
table.ManualFields = make([]*domain.Field, 0)
... ...
... ... @@ -49,6 +49,9 @@ func (ptr *PGLogService) Log(logType domain.LogType, sourceId int, logEntry Log)
if entry.OperationType == domain.UnKnown.ToString() {
return nil
}
if logEntry.LogType() != "" {
log.LogType = logEntry.LogType()
}
if v, ok := logEntry.Context().GetValue(domain.ContextWithLogLevel); ok {
log.Entry.Level = string(v.(domain.LogLevel))
... ... @@ -83,6 +86,7 @@ type Log interface {
Entry() domain.LogEntry
Context() *domain.Context
OperateType() string
LogType() string
}
var _ Log = (*FileUploadSuccessLog)(nil)
... ... @@ -351,14 +355,31 @@ func (l *CreateQuerySetLog) OperateType() string {
if l.Qs.Type == domain.SubProcessTable.ToString() && l.Qs.Flag == domain.FlagSet {
return domain.CreateSubProcess.ToString()
}
if l.Qs.Type == domain.CalculateItem.ToString() && l.Qs.Flag == domain.FlagSet {
return domain.CreateFormula.ToString()
}
if l.Qs.Type == domain.CalculateTable.ToString() && l.Qs.Flag == domain.FlagSet {
return domain.CreateFormula.ToString()
}
if l.Qs.Type == domain.CalculateSet.ToString() && l.Qs.Flag == domain.FlagSet {
return domain.CreateFormula.ToString()
}
return domain.UnKnown.ToString()
}
func (l *CreateQuerySetLog) LogType() string {
if l.Qs.Type == domain.SchemaTable.ToString() || l.Qs.Type == domain.SubProcessTable.ToString() {
return domain.QuerySetLog.ToString()
}
return domain.FormulaLog.ToString()
}
func (l *CreateQuerySetLog) Content() string {
return "新增成功"
}
type RenameQuerySetLog struct {
Qs *domain.QuerySet
domain.LogEntry
OldName string
NewName string
... ... @@ -368,6 +389,13 @@ func (l *RenameQuerySetLog) OperateType() string {
return domain.RenameQuerySet.ToString()
}
func (l *RenameQuerySetLog) LogType() string {
if l.Qs.Type == domain.SchemaTable.ToString() || l.Qs.Type == domain.SubProcessTable.ToString() {
return domain.QuerySetLog.ToString()
}
return domain.FormulaLog.ToString()
}
func (l *RenameQuerySetLog) Content() string {
return fmt.Sprintf(`"%s"重命名为"%v"`, l.OldName, l.NewName)
}
... ... @@ -384,6 +412,17 @@ func (l *DeleteQuerySetLog) OperateType() string {
return domain.DeleteQuerySet.ToString()
}
func (l *DeleteQuerySetLog) LogType() string {
if len(l.DeleteList) == 0 {
return ""
}
qs := l.DeleteList[0]
if qs.Type == domain.SchemaTable.ToString() || qs.Type == domain.SubProcessTable.ToString() {
return domain.QuerySetLog.ToString()
}
return domain.FormulaLog.ToString()
}
func (l *DeleteQuerySetLog) Content() string {
names := make([]string, 0)
for i := range l.DeleteList {
... ... @@ -406,9 +445,20 @@ func (l *CopyQuerySetLog) OperateType() string {
return domain.CopyQuerySet.ToString()
}
func (l *CopyQuerySetLog) LogType() string {
qs := l.From
if qs.Type == domain.SchemaTable.ToString() || qs.Type == domain.SubProcessTable.ToString() {
return domain.QuerySetLog.ToString()
}
return domain.FormulaLog.ToString()
}
func (l *CopyQuerySetLog) Content() string {
return fmt.Sprintf(`%s"%s"复制为%s"%s""`, domain.EnumsDescription(domain.ObjectTypeMap, l.From.Type), l.From.Name,
domain.EnumsDescription(domain.ObjectTypeMap, l.To.Type), l.To.Name)
if l.LogType() == domain.QuerySetLog.ToString() {
return fmt.Sprintf(`%s"%s"复制为%s"%s"`, domain.EnumsDescription(domain.ObjectTypeMap, l.From.Type), l.From.Name,
domain.EnumsDescription(domain.ObjectTypeMap, l.To.Type), l.To.Name)
}
return fmt.Sprintf(`"%s"复制为"%s"`, l.From.Name, l.To.Name)
}
type EditQuerySetConditionLog struct {
... ... @@ -460,3 +510,25 @@ func (l *EditSelectConditionLog) Content() string {
}
return "删除拆分规则:" + strings.Join(l.Sources, ";")
}
type EditFormulaLog struct {
domain.LogEntry
OperationType domain.OperationType // 编辑类型 1:add 2.edit 3.delete
Old string
New string
Msg string
}
func (l *EditFormulaLog) OperateType() string {
return l.OperationType.ToString()
}
func (l *EditFormulaLog) Content() string {
if len(l.Msg) > 0 {
return l.Msg
}
if len(l.Old) == 0 {
return fmt.Sprintf("修改为 %v", l.New)
}
return fmt.Sprintf("%v 修改为 %v", l.Old, l.New)
}
... ...
... ... @@ -7,6 +7,7 @@ import (
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/dao"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/redis"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/repository"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks"
"strings"
"time"
)
... ... @@ -94,7 +95,20 @@ func (ptr *QuerySetService) Update(ctx *domain.Context, querySetId int, queryCom
if err != nil {
return err
}
if qs.Type == domain.SchemaTable.ToString() || qs.Type == domain.SubProcessTable.ToString() {
return ptr.UpdateDefault(ctx, qs, queryComponents)
}
if qs.Type == domain.CalculateItem.ToString() {
return ptr.UpdateCalculateItem(ctx, qs, queryComponents)
}
if qs.Type == domain.CalculateTable.ToString() {
return ptr.UpdateCalculateTable(ctx, qs, queryComponents)
}
return nil
}
func (ptr *QuerySetService) UpdateDefault(ctx *domain.Context, qs *domain.QuerySet, queryComponents []*domain.QueryComponent) error {
querySetRepository, _ := repository.NewQuerySetRepository(ptr.transactionContext)
// 生成Table
masterTable := queryComponents[0].MasterTable
table, err := ptr.CreateOrUpdateQuerySetTable(ctx, qs, masterTable, queryComponents)
... ... @@ -137,6 +151,90 @@ func (ptr *QuerySetService) Update(ctx *domain.Context, querySetId int, queryCom
return nil
}
func (ptr *QuerySetService) UpdateCalculateItem(ctx *domain.Context, qs *domain.QuerySet, queryComponents []*domain.QueryComponent) error {
querySetRepository, _ := repository.NewQuerySetRepository(ptr.transactionContext)
// 生成Table
//masterTable := queryComponents[0].MasterTable
table, err := ptr.CreateOrUpdateCalculateItemTable(ctx, qs, nil, queryComponents)
if err != nil {
return err
}
if err = ptr.validQueryComponents(queryComponents); err != nil {
return err
}
// 调用底层的组装sql
_, err = ByteCore.FormulasGenerate(domain.ReqFormulasGenerate{
QuerySet: qs,
Table: table,
QueryComponents: queryComponents,
})
if err != nil {
return err
}
//if err = starrocks.Exec(starrocks.DB,
// starrocks.CreateViewSql(table.SQLName, table.DataFields,
// starrocks.CalculateItemViewSql(&queryComponents[0].Formula.FieldExpr),
// )); err != nil {
// return err
//}
// 生成日志
if err = ptr.UpdateQuerySetLog(ctx, qs, queryComponents); err != nil {
return err
}
// 保存
qs.Update(queryComponents, table.TableId)
_, err = querySetRepository.Save(qs)
if err != nil {
return err
}
return nil
}
func (ptr *QuerySetService) UpdateCalculateTable(ctx *domain.Context, qs *domain.QuerySet, queryComponents []*domain.QueryComponent) error {
querySetRepository, _ := repository.NewQuerySetRepository(ptr.transactionContext)
// 生成Table
masterTable := queryComponents[0].MasterTable
table, err := ptr.CreateOrUpdateCalculateTable(ctx, qs, masterTable, queryComponents)
if err != nil {
return err
}
if err = ptr.validQueryComponents(queryComponents); err != nil {
return err
}
// 调用底层的组装sql
_, err = ByteCore.FormulasGenerate(domain.ReqFormulasGenerate{
QuerySet: qs,
Table: table,
QueryComponents: queryComponents,
})
if err != nil {
return err
}
//if err = starrocks.Exec(starrocks.DB,
// starrocks.CreateViewSql(table.SQLName, table.DataFields,
// starrocks.CalculateTableViewSql(queryComponents[0].MasterTable.SQLName, &queryComponents[0].Aggregation.Aggregation),
// )); err != nil {
// return err
//}
// 生成日志
if err = ptr.UpdateQuerySetLog(ctx, qs, queryComponents); err != nil {
return err
}
// 保存
qs.Update(queryComponents, table.TableId)
_, err = querySetRepository.Save(qs)
if err != nil {
return err
}
return nil
}
func (ptr *QuerySetService) PreviewPrepare(ctx *domain.Context, querySetId int, queryComponents []*domain.QueryComponent) (*domain.Table, error) {
querySetRepository, _ := repository.NewQuerySetRepository(ptr.transactionContext)
querySet, err := querySetRepository.FindOne(map[string]interface{}{"querySetId": querySetId})
... ... @@ -159,14 +257,24 @@ func (ptr *QuerySetService) PreviewPrepare(ctx *domain.Context, querySetId int,
foundMasterTable *domain.Table
)
// 生成Table
masterTable := queryComponents[0].MasterTable
var fields = make([]*domain.Field, 0)
dependencyTables := querySet.GetDependencyTables(queryComponents)
foundMasterTable, err = tableRepository.FindOne(map[string]interface{}{"context": ctx, "tableId": masterTable.TableId})
if err != nil {
return nil, err
if querySet.Type == domain.CalculateTable.ToString() {
aggregationFields := append(queryComponents[0].Aggregation.RowFields, queryComponents[0].Aggregation.ValueFields...)
for index, f := range aggregationFields {
fields = append(fields, DataField(f.DisplayName, f.Field.SQLType, domain.MainTableField, index))
}
} else {
masterTable := queryComponents[0].MasterTable
foundMasterTable, err = tableRepository.FindOne(map[string]interface{}{"context": ctx, "tableId": masterTable.TableId})
if err != nil {
return nil, err
}
masterTable = domain.NewQueryComponentTable(foundMasterTable)
fields = masterTable.Fields
}
masterTable = domain.NewQueryComponentTable(foundMasterTable)
var table *domain.Table = NewCopyTable(domain.TableType(domain.TemporaryTable), querySet.Name, domain.RangeFields(masterTable.Fields, domain.ChangeFieldFlag), 0).
var table *domain.Table = NewCopyTable(domain.TableType(domain.TemporaryTable), querySet.Name, domain.RangeFields(fields, domain.ChangeFieldFlag), 0).
WithContext(ctx).
WithPrefix(strings.ToLower(string(domain.TemporaryTable)))
// 循环依赖判断
... ... @@ -258,7 +366,12 @@ func (ptr *QuerySetService) UpdateQuerySetLog(ctx *domain.Context, querySet *dom
if logs := selectsEditLog(ctx, querySet, queryComponents); len(logs) > 0 {
res = append(res, logs...)
}
if logs := formulaEditLog(ctx, querySet, queryComponents); len(logs) > 0 {
res = append(res, logs...)
}
if logs := aggregationEditLog(ctx, querySet, queryComponents); len(logs) > 0 {
res = append(res, logs...)
}
for _, l := range res {
FastLog(ptr.transactionContext, l.LogType, l.SourceId, l.LogEntry)
}
... ... @@ -350,23 +463,6 @@ func conditionsEditLog(ctx *domain.Context, querySet *domain.QuerySet, queryComp
return res
}
func queryComponentsHasEdit(ctx *domain.Context, querySet *domain.QuerySet, queryComponents []*domain.QueryComponent) bool {
logs := selectsEditLog(ctx, querySet, queryComponents)
if len(logs) > 0 {
return true
}
logs = conditionsEditLog(ctx, querySet, queryComponents)
if len(logs) > 0 {
return true
}
for _, item := range queryComponents {
if len(item.Id) == 0 {
return true
}
}
return false
}
func selectsEditLog(ctx *domain.Context, querySet *domain.QuerySet, queryComponents []*domain.QueryComponent) []FastSourceLog {
var res = make([]FastSourceLog, 0)
oldQCs := domain.QueryComponentsToMapById(querySet.QueryComponents)
... ... @@ -451,7 +547,88 @@ func selectsEditLog(ctx *domain.Context, querySet *domain.QuerySet, queryCompone
return res
}
func (ptr *QuerySetService) CreateOrUpdateQuerySetTable(ctx *domain.Context, querySet *domain.QuerySet, masterTable domain.QueryComponentTable, queryComponents []*domain.QueryComponent) (*domain.Table, error) {
func formulaEditLog(ctx *domain.Context, querySet *domain.QuerySet, queryComponents []*domain.QueryComponent) []FastSourceLog {
var res = make([]FastSourceLog, 0)
sourceId := querySet.QuerySetId
entry := domain.NewLogEntry(querySet.Name, querySet.Type, domain.UnKnown, ctx)
if len(queryComponents) > 0 && len(querySet.QueryComponents) > 0 {
oldQC := querySet.QueryComponents[0]
newQC := queryComponents[0]
if oldQC.Formula == nil || newQC.Formula == nil {
return res
}
if oldQC.Formula.ExprSql != newQC.Formula.ExprSql {
res = append(res, NewFastSourceLog(domain.QuerySetLog, sourceId, &EditFormulaLog{
LogEntry: entry,
OperationType: domain.EditCalculateItem,
Old: oldQC.Formula.ExprHuman,
New: newQC.Formula.ExprHuman,
}))
}
}
return res
}
func aggregationEditLog(ctx *domain.Context, querySet *domain.QuerySet, queryComponents []*domain.QueryComponent) []FastSourceLog {
var res = make([]FastSourceLog, 0)
sourceId := querySet.QuerySetId
entry := domain.NewLogEntry(querySet.Name, querySet.Type, domain.UnKnown, ctx)
if len(queryComponents) > 0 && len(querySet.QueryComponents) > 0 {
oldQC := querySet.QueryComponents[0]
newQC := queryComponents[0]
if oldQC.Aggregation == nil || newQC.Aggregation == nil {
return res
}
mapOldAgFields := make(map[string]*domain.AggregationField)
for _, f := range oldQC.Aggregation.AggregationFields() {
mapOldAgFields[f.DisplayName] = f
}
changList := make([]string, 0)
for _, f := range newQC.Aggregation.AggregationFields() {
if v, ok := mapOldAgFields[f.DisplayName]; ok {
if f.Diff(v) {
changList = append(changList, fmt.Sprintf("%s修改为%s", v.Info(), f.Info()))
}
}
}
if len(changList) > 0 {
res = append(res, NewFastSourceLog(domain.QuerySetLog, sourceId, &EditFormulaLog{
LogEntry: entry,
OperationType: domain.EditCalculateTable,
Msg: strings.Join(changList, ";"),
}))
}
}
return res
}
func queryComponentsHasEdit(ctx *domain.Context, querySet *domain.QuerySet, queryComponents []*domain.QueryComponent) bool {
logs := selectsEditLog(ctx, querySet, queryComponents)
if len(logs) > 0 {
return true
}
logs = conditionsEditLog(ctx, querySet, queryComponents)
if len(logs) > 0 {
return true
}
logs = aggregationEditLog(ctx, querySet, queryComponents)
if len(logs) > 0 {
return true
}
for _, item := range queryComponents {
if len(item.Id) == 0 {
return true
}
}
return false
}
// CreateOrUpdateQuerySetTable 计算集
func (ptr *QuerySetService) CreateOrUpdateQuerySetTable(ctx *domain.Context, querySet *domain.QuerySet, masterTable *domain.QueryComponentTable, queryComponents []*domain.QueryComponent) (*domain.Table, error) {
var (
err error
foundMasterTable *domain.Table
... ... @@ -487,6 +664,80 @@ func (ptr *QuerySetService) CreateOrUpdateQuerySetTable(ctx *domain.Context, que
return table, nil
}
// CreateOrUpdateCalculateItemTable 计算项
func (ptr *QuerySetService) CreateOrUpdateCalculateItemTable(ctx *domain.Context, querySet *domain.QuerySet, masterTable *domain.QueryComponentTable, queryComponents []*domain.QueryComponent) (*domain.Table, error) {
var (
err error
)
dependencyTables := querySet.GetDependencyTables(queryComponents)
tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
queryComponent := queryComponents[0]
field := DataField(querySet.Name, domain.String.ToString(), domain.MainTableField, 1)
if len(queryComponent.Formula.TableFields) > 0 {
field.SQLType = queryComponent.Formula.TableFields[0].FieldSQLType
}
var table *domain.Table = NewCopyTable(domain.TableType(querySet.Type), querySet.Name, []*domain.Field{field}, 1).WithContext(ctx).WithPrefix(strings.ToLower(querySet.Type))
table.PK = nil
if querySet.QuerySetInfo.BindTableId > 0 {
table, err = tableRepository.FindOne(map[string]interface{}{"context": ctx, "tableId": querySet.QuerySetInfo.BindTableId})
if err != nil {
return nil, err
}
table.DataFields = []*domain.Field{field}
table.UpdatedAt = time.Now()
}
table.TableInfo.ApplyOnModule = domain.ModuleAll
table.TableInfo.DependencyTables = dependencyTables
table, err = tableRepository.Save(table)
if err != nil {
return nil, err
}
return table, nil
}
// CreateOrUpdateCalculateTable 计算表
func (ptr *QuerySetService) CreateOrUpdateCalculateTable(ctx *domain.Context, querySet *domain.QuerySet, masterTable *domain.QueryComponentTable, queryComponents []*domain.QueryComponent) (*domain.Table, error) {
var (
err error
foundMasterTable *domain.Table
)
dependencyTables := querySet.GetDependencyTables(queryComponents)
tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
foundMasterTable, err = tableRepository.FindOne(map[string]interface{}{"context": ctx, "tableId": masterTable.TableId})
if err != nil {
return nil, err
}
masterTable = domain.NewQueryComponentTable(foundMasterTable)
queryComponent := queryComponents[0]
queryComponent.MasterTable = masterTable
fields := make([]*domain.Field, 0)
aggregationFields := queryComponent.Aggregation.AggregationFields()
selectedFields := make([]string, 0)
for index, f := range aggregationFields {
fields = append(fields, DataField(f.DisplayName, f.Field.SQLType, domain.MainTableField, index))
selectedFields = append(selectedFields, f.Field.Name)
}
queryComponent.Aggregation.SelectFields = selectedFields
var table *domain.Table = NewCopyTable(domain.TableType(querySet.Type), querySet.Name, fields, 0).WithContext(ctx).WithPrefix(strings.ToLower(querySet.Type))
if querySet.QuerySetInfo.BindTableId > 0 {
table, err = tableRepository.FindOne(map[string]interface{}{"context": ctx, "tableId": querySet.QuerySetInfo.BindTableId})
if err != nil {
return nil, err
}
table.DataFields = fields
table.UpdatedAt = time.Now()
}
table.TableInfo.ApplyOnModule = domain.ModuleAll
table.TableInfo.DependencyTables = dependencyTables
table, err = tableRepository.Save(table)
if err != nil {
return nil, err
}
return table, nil
}
func (ptr *QuerySetService) Rename(ctx *domain.Context, querySetId int, name string) error {
querySetRepository, _ := repository.NewQuerySetRepository(ptr.transactionContext)
qs, err := querySetRepository.FindOne(map[string]interface{}{"querySetId": querySetId})
... ... @@ -520,6 +771,7 @@ func (ptr *QuerySetService) Rename(ctx *domain.Context, querySetId int, name str
// 日志
if err = FastLog(ptr.transactionContext, domain.QuerySetLog, qs.QuerySetId, &RenameQuerySetLog{
LogEntry: domain.NewLogEntry(qs.Name, qs.Type, domain.UnKnown, ctx),
Qs: qs,
NewName: name,
OldName: oldName,
}); err != nil {
... ... @@ -537,7 +789,7 @@ func (ptr *QuerySetService) ChangeStatus(ctx *domain.Context, querySetId int, st
if qs.Status == status {
return nil
}
if qs.Type != domain.SchemaTable.ToString() {
if !domain.TableType(qs.Type).TableStatusEditable() {
return fmt.Errorf("方案才可以修改状态")
}
qs.Status = status
... ... @@ -593,7 +845,6 @@ func (ptr *QuerySetService) Copy(ctx *domain.Context, querySetId int, t string,
return nil, err
}
copyTable := NewCopyTable(domain.TableType(t), name, table.Fields(false), 0).WithContext(ctx).WithPrefix(qs.Type)
copyTable, err = tableRepository.Save(copyTable)
if err != nil {
return nil, err
... ... @@ -609,12 +860,12 @@ func (ptr *QuerySetService) Copy(ctx *domain.Context, querySetId int, t string,
return nil, err
}
if len(formulasGenerateResponse.FormulaName) > 0 && formulasGenerateResponse.FormulaName != table.SQLName {
copyTable.SQLName = formulasGenerateResponse.FormulaName
tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
copyTable, err = tableRepository.Save(copyTable)
if err != nil {
return nil, err
}
//copyTable.SQLName = formulasGenerateResponse.FormulaName
//tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
//copyTable, err = tableRepository.Save(copyTable)
//if err != nil {
// return nil, err
//}
}
copy.QuerySetInfo.BindTableId = copyTable.TableId
}
... ... @@ -622,6 +873,14 @@ func (ptr *QuerySetService) Copy(ctx *domain.Context, querySetId int, t string,
if err != nil {
return nil, err
}
// 日志
if err = FastLog(ptr.transactionContext, domain.QuerySetLog, qs.QuerySetId, &CopyQuerySetLog{
LogEntry: domain.NewLogEntry(qs.Name, qs.Type, domain.UnKnown, ctx),
From: qs,
To: copy,
}); err != nil {
return nil, err
}
return copy, nil
}
... ... @@ -649,21 +908,29 @@ func (ptr *QuerySetService) Delete(ctx *domain.Context, querySetId int) error {
return err
}
querySetRepository, _ := repository.NewQuerySetRepository(ptr.transactionContext)
tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
tableDependencyService, _ := NewTableDependencyService(ptr.transactionContext)
// 1.判断依赖,删除表
for i := range querySets {
if _, err := querySetRepository.Remove(querySets[i]); err != nil {
return err
}
if querySets[i].Flag != domain.FlagGroup && querySets[i].Type == domain.SchemaTable.ToString() && querySets[i].Status == domain.StatusOn {
if querySets[i].Flag != domain.FlagGroup &&
domain.TableType(querySets[i].Type).TableStatusEditable() &&
querySets[i].Status == domain.StatusOn {
return ErrQuerySetDeleteStatusOn
}
if querySets[i].QuerySetInfo.BindTableId > 0 {
if err := tableDependencyService.HasDependencyError(ctx, querySets[i].QuerySetInfo.BindTableId); err != nil {
tableId := querySets[i].QuerySetInfo.BindTableId
if tableId > 0 {
if err := tableDependencyService.HasDependencyError(ctx, tableId); err != nil {
return err
}
if err := dao.TableSoftDelete(ptr.transactionContext, querySets[i].QuerySetInfo.BindTableId, domain.TableType(querySets[i].Type)); err != nil {
return err
t, _ := tableRepository.FindOne(map[string]interface{}{"tableId": tableId})
if t != nil {
if err := dao.TableSoftDelete(ptr.transactionContext, tableId, domain.TableType(querySets[i].Type)); err != nil {
return err
}
starrocks.DropView(starrocks.DB, t.SQLName)
}
}
}
... ...
... ... @@ -25,6 +25,8 @@ type Table struct {
DataFields []*domain.Field `comment:"数据列"`
// 手动添加的列
ManualFields []*domain.Field `comment:"手动添加的列"`
// 默认排序列
//OrderFields []*domain.Field `comment:"默认排序列"`
// 创建时间
CreatedAt time.Time `comment:"创建时间"`
// 更新时间
... ...
... ... @@ -161,6 +161,9 @@ func (repository *QuerySetRepository) Find(queryOptions map[string]interface{})
query.SetWhereByQueryOption("flag = ?", "flag")
query.SetWhereByQueryOption("status = ?", "status")
query.SetWhereByQueryOption(fmt.Sprintf("name like '%%%v%%'", queryOptions["matchName"]), "matchName")
if v, ok := queryOptions["types"]; ok && len(v.([]string)) > 0 {
query.Where("type in (?)", pg.In(v))
}
if v, ok := queryOptions["inParentIds"]; ok && len(v.([]int)) > 0 {
query.Where("parent_id in (?)", pg.In(v))
}
... ...
... ... @@ -167,7 +167,7 @@ func (repository *TableRepository) Find(queryOptions map[string]interface{}) (in
query := sqlbuilder.BuildQuery(tx.Model(&tableModels), queryOptions)
WhereContext(query, queryOptions)
query.SetWhereByQueryOption(fmt.Sprintf("name like '%%%v%%'", queryOptions["name"]), "name")
query.SetWhereByQueryOption("table_id = ?", "tableId")
query.SetWhereByQueryOption("parent_id = ?", "parentId")
if v, ok := queryOptions["tableIds"]; ok && len(v.([]int)) > 0 {
query.Where(`table_id in (?)`, pg.In(v.([]int)))
... ...
package starrocks
import (
"bytes"
"fmt"
"github.com/google/uuid"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"gorm.io/gorm"
"html"
"html/template"
)
func Insert(db *gorm.DB, tableName string, fields []*domain.FieldValue) error {
... ... @@ -72,3 +75,36 @@ func DropView(db *gorm.DB, tableName string) error {
tx := db.Exec("DROP VIEW IF EXISTS " + tableName)
return tx.Error
}
func Exec(db *gorm.DB, sql string) error {
tx := db.Exec(sql)
return tx.Error
}
func CreateViewSql(viewName string, fields []*domain.Field, selectSql string) string {
sql := `
DROP VIEW IF EXISTS {{.ViewName}};
create view {{.ViewName}}(
{{.Field}}
) as(
{{.Sql}}
)
`
tmp := template.New("ViewCreator")
tmp.Parse(sql)
buf := bytes.NewBuffer(nil)
bufField := bytes.NewBuffer(nil)
for i, f := range fields {
bufField.WriteString(fmt.Sprintf(`%s COMMENT "%v"`, f.SQLName, f.Name))
if i != len(fields)-1 {
bufField.WriteString(",\n")
}
}
tmp.Execute(buf, map[string]interface{}{
"ViewName": viewName,
"Field": bufField.String(),
"Sql": selectSql,
})
return html.UnescapeString(buf.String())
}
... ...
... ... @@ -3,6 +3,7 @@ package starrocks
import (
"database/sql"
"fmt"
"github.com/zeromicro/go-zero/core/collection"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/utils"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
... ... @@ -66,6 +67,15 @@ func (o *QueryOptions) SetDefaultOrder() *QueryOptions {
// 没有排序的加一个排序,才能分页
if !hasOrder {
if o.Table != nil {
if o.Table.PK == nil {
//o.Where = append(o.Where, Condition{
// Condition: domain.Condition{
// Field: o.Table.DataFields[0],
// Order: "ASC",
// },
//})
return o
}
o.Where = append(o.Where, Condition{
Condition: domain.Condition{
Field: o.Table.PK,
... ... @@ -105,6 +115,14 @@ func (o *QueryOptions) AdditionOptionsByTable(table *domain.Table) *QueryOptions
},
In: []interface{}{domain.QuerySetLog.ToString()},
}})
case domain.DBTableFormulaLog.ToInt():
o.SetCondition([]domain.Condition{{
Field: &domain.Field{
SQLName: "log_type",
SQLType: domain.String.ToString(),
},
In: []interface{}{domain.FormulaLog.ToString()},
}})
}
return o
}
... ... @@ -280,7 +298,7 @@ func queryWithoutLimitOffset(query *gorm.DB, params QueryOptions) {
}
if len(params.Where) > 0 {
for _, w := range params.Where {
if w.Field.Flag == domain.ManualField {
if w.Field != nil && w.Field.Flag == domain.ManualField {
continue
}
w.SetWhere(params, query)
... ... @@ -386,3 +404,66 @@ func WrapQueryHasDuplicateRowBySql(sql string, db *gorm.DB) func() (int64, int64
return total, duplicateTotal, nil
}
}
func WrapQueryHasDuplicateRowBySqlParam1(sql string, db *gorm.DB, result1 interface{}) error {
query := db.Raw(sql)
row := query.Row()
if row.Err() != nil {
return row.Err()
}
if err := row.Scan(result1); err != nil {
return err
}
return nil
}
func CalculateItemValue(db *gorm.DB, fieldExpr *domain.FieldExpr) string {
var value string
sql := CalculateItemViewSql(fieldExpr)
WrapQueryHasDuplicateRowBySqlParam1(sql, db, &value)
return value
}
func CalculateItemViewSql(fieldExpr *domain.FieldExpr) string {
sql := "select " + fieldExpr.ExprSql
tables := collection.NewSet()
for _, f := range fieldExpr.TableFields {
if len(f.TableSqlName) == 0 {
continue
}
tables.AddStr(f.TableSqlName)
}
if len(tables.KeysStr()) > 0 {
sql += fmt.Sprintf(" from %v", strings.Join(tables.KeysStr(), ","))
}
return sql
}
func CalculateTableViewSql(table string, aggregation *domain.Aggregation) string {
columns := make([]string, 0)
groups := make([]string, 0)
orders := make([]string, 0)
for _, f := range aggregation.RowFields {
columns = append(columns, f.Expr.ExprSql)
if f.Order != "" {
orders = append(orders, fmt.Sprintf("%v %v", f.Field.SQLName, f.Order))
}
groups = append(groups, f.Field.SQLName)
}
for _, f := range aggregation.ValueFields {
columns = append(columns, f.Expr.ExprSql)
if f.Order != "" {
orders = append(orders, fmt.Sprintf("%v %v", f.Field.SQLName, f.Order))
}
}
sql := "select " + strings.Join(columns, ",")
sql += fmt.Sprintf("\nfrom %v", table)
if len(groups) > 0 {
sql += "\ngroup by " + strings.Join(groups, ",")
}
if len(orders) > 0 {
sql += "\norder by " + strings.Join(orders, ",")
}
return sql
}
... ...
... ... @@ -16,7 +16,7 @@ import (
func init() {
web.BConfig.AppName = "character-library-metadata-bastion"
web.BConfig.CopyRequestBody = true
web.BConfig.RunMode = "dev"
web.BConfig.RunMode = "dev" //"prod"
web.BConfig.Listen.HTTPPort = 8080
web.BConfig.Listen.EnableAdmin = false
web.BConfig.WebConfig.CommentRouterPath = "/pkg/port/beego/routers"
... ...
... ... @@ -37,6 +37,22 @@ func (controller *QuerySetController) PreviewPrepare() {
controller.Response(data, err)
}
func (controller *QuerySetController) CalculateItemPreview() {
querySetService := service.NewQuerySetService(nil)
updateQuerySetCommand := &query.CalculateItemPreviewQuery{}
Must(controller.Unmarshal(updateQuerySetCommand))
data, err := querySetService.CalculateItemPreview(ParseContext(controller.BaseController), updateQuerySetCommand)
controller.Response(data, err)
}
func (controller *QuerySetController) CalculateItemExport() {
querySetService := service.NewQuerySetService(nil)
updateQuerySetCommand := &query.CalculateItemPreviewQuery{}
Must(controller.Unmarshal(updateQuerySetCommand))
data, err := querySetService.CalculateItemExport(ParseContext(controller.BaseController), updateQuerySetCommand)
controller.Response(data, err)
}
func (controller *QuerySetController) GetQuerySet() {
querySetService := service.NewQuerySetService(nil)
getQuerySetQuery := &query.GetQuerySetQuery{}
... ...
... ... @@ -107,7 +107,7 @@ func (controller *TableController) Search() {
func (controller *TableController) RelationGraph() {
tableService := service.NewTableService(nil)
cmd := &query.SearchTableQuery{}
cmd := &query.SearchTableRelationGraphQuery{}
Must(controller.Unmarshal(cmd))
cmd.TableTypes = []string{domain.MainTable.ToString(), domain.SideTable.ToString(), domain.SubTable.ToString()}
cmd.Context = ParseContext(controller.BaseController)
... ... @@ -149,6 +149,15 @@ func (controller *TableController) SearchQuerySetTables() {
controller.Response(data, err)
}
func (controller *TableController) TableObjectSearch() {
tableService := service.NewTableService(nil)
cmd := &query.SearchTableQuery{}
Must(controller.Unmarshal(cmd))
cmd.Context = ParseContext(controller.BaseController)
data, err := tableService.TableObjectSearch(cmd)
controller.Response(data, err)
}
func (controller *TableController) UpdateTableStruct() {
tableService := service.NewTableService(nil)
cmd := &command.UpdateTableStructCommand{}
... ...
... ... @@ -19,4 +19,19 @@ func init() {
web.Router("/data/query-sets/rename", &controllers.QuerySetController{}, "Post:Rename")
web.Router("/data/query-sets/search", &controllers.QuerySetController{}, "Post:SearchQuerySet")
web.Router("/data/query-sets/preview-prepare", &controllers.QuerySetController{}, "Post:PreviewPrepare")
web.Router("/data/query-sets/formula/", &controllers.QuerySetController{}, "Post:CreateQuerySet")
web.Router("/data/query-sets/formula/:querySetId", &controllers.QuerySetController{}, "Put:UpdateQuerySet")
web.Router("/data/query-sets/formula/:querySetId", &controllers.QuerySetController{}, "Get:GetQuerySet")
web.Router("/data/query-sets/formula/:querySetId", &controllers.QuerySetController{}, "Delete:RemoveQuerySet")
web.Router("/data/query-sets/formula/change-status", &controllers.QuerySetController{}, "Post:ChangeStatus")
web.Router("/data/query-sets/formula/copy", &controllers.QuerySetController{}, "Post:Copy")
web.Router("/data/query-sets/formula/move", &controllers.QuerySetController{}, "Post:Move")
web.Router("/data/query-sets/formula/rename", &controllers.QuerySetController{}, "Post:Rename")
web.Router("/data/query-sets/formula/search", &controllers.QuerySetController{}, "Post:SearchQuerySet")
web.Router("/data/query-sets/formula/calculate-table-preview-prepare", &controllers.QuerySetController{}, "Post:PreviewPrepare")
web.Router("/data/query-sets/formula/calculate-item-preview", &controllers.QuerySetController{}, "Post:CalculateItemPreview")
web.Router("/data/query-sets/formula/calculate-item-export", &controllers.QuerySetController{}, "Post:CalculateItemExport")
}
... ...
... ... @@ -33,8 +33,9 @@ func init() {
web.Router("/data/tables/row-edit", &controllers.TableController{}, "Post:RowEdit")
web.Router("/data/field-optional-values", &controllers.TableController{}, "Post:FieldOptionalValues")
web.Router("/data/table-object-search", &controllers.TableController{}, "Post:TableObjectSearch")
web.Router("/business/db-table-preview", &controllers.TableController{}, "Post:DBTablePreview")
web.Router("/data/table-preview", &controllers.TableController{}, "Post:Preview")
}
... ...