feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
186
backend/domain/knowledge/service/rdb.go
Normal file
186
backend/domain/knowledge/service/rdb.go
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
knowledgeModel "github.com/coze-dev/coze-studio/backend/api/model/crossdomain/knowledge"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/knowledge/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/knowledge/internal/consts"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/knowledge/internal/convert"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/knowledge/internal/dal/model"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/document"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/rdb"
|
||||
rdbEntity "github.com/coze-dev/coze-studio/backend/infra/contract/rdb/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/logs"
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
)
|
||||
|
||||
func (k *knowledgeSVC) selectTableData(ctx context.Context, tableInfo *entity.TableInfo, slices []*model.KnowledgeDocumentSlice) (sliceEntityMap map[int64]*entity.Slice, err error) {
|
||||
sliceEntityMap = map[int64]*entity.Slice{}
|
||||
var sliceIDs []int64
|
||||
for i := range slices {
|
||||
sliceIDs = append(sliceIDs, slices[i].ID)
|
||||
}
|
||||
resp, err := k.rdb.SelectData(ctx, &rdb.SelectDataRequest{
|
||||
TableName: tableInfo.PhysicalTableName,
|
||||
Fields: nil,
|
||||
Where: &rdb.ComplexCondition{
|
||||
Conditions: []*rdb.Condition{
|
||||
{
|
||||
Field: consts.RDBFieldID,
|
||||
Operator: rdbEntity.OperatorIn,
|
||||
Value: sliceIDs,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "execute sql failed, err: %v", err)
|
||||
return nil, errorx.New(errno.ErrKnowledgeCrossDomainCode, errorx.KV("msg", err.Error()))
|
||||
}
|
||||
rows := resp.ResultSet.Rows
|
||||
virtualColumnMap := map[string]*entity.TableColumn{}
|
||||
for i := range tableInfo.Columns {
|
||||
virtualColumnMap[convert.ColumnIDToRDBField(tableInfo.Columns[i].ID)] = tableInfo.Columns[i]
|
||||
}
|
||||
valMap := map[int64]map[string]interface{}{}
|
||||
for i := range rows {
|
||||
sliceID, ok := rows[i][consts.RDBFieldID].(int64)
|
||||
if !ok {
|
||||
logs.CtxErrorf(ctx, "slice id is not int64")
|
||||
return nil, errorx.New(errno.ErrKnowledgeSystemCode, errorx.KV("msg", "slice id is not int64"))
|
||||
}
|
||||
delete(rows[i], consts.RDBFieldID)
|
||||
valMap[sliceID] = resp.ResultSet.Rows[i]
|
||||
}
|
||||
for i := range slices {
|
||||
sliceEntity := k.fromModelSlice(ctx, slices[i])
|
||||
sliceEntity.RawContent = make([]*knowledgeModel.SliceContent, 0)
|
||||
sliceEntity.RawContent = append(sliceEntity.RawContent, &knowledgeModel.SliceContent{
|
||||
Type: knowledgeModel.SliceContentTypeTable,
|
||||
Table: &knowledgeModel.SliceTable{},
|
||||
})
|
||||
for cName, val := range valMap[slices[i].ID] {
|
||||
column, found := virtualColumnMap[cName]
|
||||
if !found {
|
||||
logs.CtxInfof(ctx, "column not found, name: %s", cName)
|
||||
continue
|
||||
}
|
||||
columnData, err := convert.ParseAnyData(column, val)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "parse any data failed: %v", err)
|
||||
return nil, errorx.New(errno.ErrKnowledgeColumnParseFailCode, errorx.KV("msg", err.Error()))
|
||||
}
|
||||
if columnData.Type == document.TableColumnTypeString {
|
||||
columnData.ValString = ptr.Of(k.formatSliceContent(ctx, columnData.GetStringValue()))
|
||||
}
|
||||
if columnData.Type == document.TableColumnTypeImage {
|
||||
columnData.ValImage = ptr.Of(k.formatSliceContent(ctx, columnData.GetStringValue()))
|
||||
}
|
||||
sliceEntity.RawContent[0].Table.Columns = append(sliceEntity.RawContent[0].Table.Columns, columnData)
|
||||
}
|
||||
sliceEntityMap[sliceEntity.ID] = sliceEntity
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (k *knowledgeSVC) alterTableSchema(ctx context.Context, beforeColumns []*entity.TableColumn, targetColumns []*entity.TableColumn, physicalTableName string) (finalColumns []*entity.TableColumn, err error) {
|
||||
alterRequest := &rdb.AlterTableRequest{
|
||||
TableName: physicalTableName,
|
||||
Operations: []*rdb.AlterTableOperation{},
|
||||
}
|
||||
finalColumns = make([]*entity.TableColumn, 0)
|
||||
for i := range targetColumns {
|
||||
if targetColumns[i] == nil {
|
||||
continue
|
||||
}
|
||||
if targetColumns[i].Name == consts.RDBFieldID {
|
||||
continue
|
||||
}
|
||||
if targetColumns[i].ID == 0 {
|
||||
// 要新增的列
|
||||
columnID, err := k.idgen.GenID(ctx)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "gen id failed, err: %v", err)
|
||||
return nil, errorx.New(errno.ErrKnowledgeIDGenCode)
|
||||
}
|
||||
targetColumns[i].ID = columnID
|
||||
alterRequest.Operations = append(alterRequest.Operations, &rdb.AlterTableOperation{
|
||||
Action: rdbEntity.AddColumn,
|
||||
Column: &rdbEntity.Column{
|
||||
Name: convert.ColumnIDToRDBField(columnID),
|
||||
DataType: convert.ConvertColumnType(targetColumns[i].Type),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
if checkColumnExist(targetColumns[i].ID, beforeColumns) {
|
||||
// 要修改的列
|
||||
alterRequest.Operations = append(alterRequest.Operations, &rdb.AlterTableOperation{
|
||||
Action: rdbEntity.ModifyColumn,
|
||||
Column: &rdbEntity.Column{
|
||||
Name: convert.ColumnIDToRDBField(targetColumns[i].ID),
|
||||
DataType: convert.ConvertColumnType(targetColumns[i].Type),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
finalColumns = append(finalColumns, targetColumns[i])
|
||||
}
|
||||
for i := range beforeColumns {
|
||||
if beforeColumns[i] == nil {
|
||||
continue
|
||||
}
|
||||
if beforeColumns[i].Name == consts.RDBFieldID {
|
||||
finalColumns = append(finalColumns, beforeColumns[i])
|
||||
continue
|
||||
}
|
||||
if !checkColumnExist(beforeColumns[i].ID, targetColumns) {
|
||||
// 要删除的列
|
||||
alterRequest.Operations = append(alterRequest.Operations, &rdb.AlterTableOperation{
|
||||
Action: rdbEntity.DropColumn,
|
||||
Column: &rdbEntity.Column{
|
||||
Name: convert.ColumnIDToRDBField(beforeColumns[i].ID),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
if len(alterRequest.Operations) == 0 {
|
||||
return targetColumns, nil
|
||||
}
|
||||
_, err = k.rdb.AlterTable(ctx, alterRequest)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "[alterTableSchema] alter table failed, err: %v", err)
|
||||
return nil, errorx.New(errno.ErrKnowledgeCrossDomainCode, errorx.KV("msg", err.Error()))
|
||||
}
|
||||
return finalColumns, nil
|
||||
}
|
||||
|
||||
func checkColumnExist(columnID int64, columns []*entity.TableColumn) bool {
|
||||
for i := range columns {
|
||||
if columns[i] == nil {
|
||||
continue
|
||||
}
|
||||
if columns[i].ID == columnID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user