table_update_table_struct_service.go 5.2 KB
package domainService

import (
	"fmt"
	pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
	"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/repository"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/utils"
	"time"
)

type UpdateTableStructService struct {
	transactionContext *pgTransaction.TransactionContext
}

func NewUpdateTableStructService(transactionContext *pgTransaction.TransactionContext) (*UpdateTableStructService, error) {
	if transactionContext == nil {
		return nil, fmt.Errorf("transactionContext参数不能为nil")
	} else {
		return &UpdateTableStructService{
			transactionContext: transactionContext,
		}, nil
	}
}

// UpdateTableStruct 更新表结构
func (ptr *UpdateTableStructService) UpdateTableStruct(ctx *domain.Context, tableId int, fields []*domain.Field, name string) (interface{}, error) {
	tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
	table, err := tableRepository.FindOne(map[string]interface{}{"tableId": tableId})
	if err != nil {
		return nil, err
	}
	if table.TableType != domain.SubTable.ToString() {
		return nil, fmt.Errorf("只有分表允许编辑表结构")
	}
	mainTable, err := tableRepository.FindOne(map[string]interface{}{"tableId": table.ParentId})
	if err != nil {
		return nil, fmt.Errorf("主表不存在")
	}

	fields = MappingFieldsV2(mainTable, fields)
	reserves, deletes, adds := domain.FieldsChange(table.Fields(false), fields)
	dataFields := (domain.Fields)(fields).Select(map[string]interface{}{"flag": domain.MainTableField})
	manualFields := (domain.Fields)(fields).Select(map[string]interface{}{"flag": domain.ManualField})
	table.DataFieldIndex = mainTable.DataFieldIndex
	table.DataFields = dataFields
	table.ManualFields = manualFields
	table.UpdatedAt = time.Now()

	if err = domain.ValidFields(fields); err != nil {
		return nil, err
	}

	if _, err = tableRepository.Save(table); err != nil {
		return nil, err
	}
	if _, err = tableRepository.Save(mainTable); err != nil {
		return nil, err
	}
	// 字段被删除
	if len(deletes) > 0 {
		tableDependencyService, _ := NewTableDependencyService(ptr.transactionContext)
		if err := tableDependencyService.HasDependencyError(ctx, tableId); err != nil {
			return nil, err
		}
	}
	defer func() {
		AsyncEvent(domain.NewEventTable(ctx, domain.TableStructEditEvent).WithTable(table))
	}()
	// 日志
	if err = FastLog(ptr.transactionContext, domain.CommonLog, table.TableId, &SubTableEditLog{
		LogEntry: domain.NewLogEntry(table.Name, table.TableType, domain.EditSubTable, ctx),
		Reserve:  reserves,
		Delete:   deletes,
		Add:      adds,
	}); err != nil {
		return nil, err
	}
	// 通知底层
	if _, err = ByteCore.SplitTable(domain.ReqSplitTable{FromTable: mainTable, ToSubTable: table}); err != nil {
		return nil, err
	}
	return struct{}{}, nil
}

// DependencyTables 依赖的表列表
func DependencyTables(ptr *pgTransaction.TransactionContext, context *domain.Context, tableId int) ([]TableNode, error) {
	ret := make([]TableNode, 0)
	// tableId 相关联的
	tableRepository, _ := repository.NewTableRepository(ptr)
	_, tables, err := tableRepository.Find(map[string]interface{}{"context": context, "tableTypesNotIn": []string{domain.TemporaryTable.ToString(), domain.ExcelTable.ToString()}})
	if err != nil {
		return nil, err
	}

	tableDependencyService, _ := NewTableDependencyService(ptr)
	tableDependTree := tableDependencyService.TableDependTree(tables, tableId)
	set := collection.NewSet()
	stack := utils.NewEmptyStack()
	list := make([]int, 0)
	stack.Push(tableId)
	for {
		item := stack.Pop()
		if item == nil {
			break
		}
		id := item.(int)
		for _, edge := range tableDependTree.Edges {
			if edge.DependChildId == id {
				stack.Push(edge.Id)
				if !set.Contains(edge.Id) {
					set.Add(edge.Id)
					list = append(list, edge.Id)
				}
			}
		}
	}
	if len(list) > 0 {
		querySetRepository, _ := repository.NewQuerySetRepository(ptr)
		_, querySets, _ := querySetRepository.Find(map[string]interface{}{"context": context, "bindTableIds": list})
		for _, id := range list {
			if v, ok := tableDependencyService.TableMap[id]; ok {
				node := NewTableNode(v)
				for _, q := range querySets {
					if q.QuerySetInfo.BindTableId == node.TableId {
						node.QuerySetId = q.QuerySetId
						break
					}
				}
				ret = append(ret, node)
			}
		}
	}
	return ret, nil
}

func MappingFieldsV2(mainTable *domain.Table, fields []*domain.Field) []*domain.Field {
	tableFields := mainTable.Fields(false)
	tableFieldsMap := (domain.Fields)(tableFields).ToMap()
	builder := NewDataFieldsBuilder()
	for i := range fields {
		f := fields[i]
		if v, ok := tableFieldsMap[f.Name]; ok {
			fields[i].Name = v.Name
			fields[i].SQLName = v.SQLName
			fields[i].Index = v.Index
			fields[i].SQLType = v.SQLType
			fields[i].Description = f.Description
			fields[i].Flag = v.Flag
			builder.NewDataField(v.Name, v.SQLType, v.Flag)
		} else {
			if f.Flag == domain.ManualField {
				fields[i] = builder.NewDataField(f.Name, f.SQLType, domain.ManualField)
				fields[i].Description = f.Description
			}
		}
	}
	return fields
}