102 lines
2.7 KiB
Go
102 lines
2.7 KiB
Go
package knowledgeversion
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/sha256"
|
||
|
|
"encoding/hex"
|
||
|
|
"encoding/json"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/Tencent/WeKnora/internal/types"
|
||
|
|
"gorm.io/gorm"
|
||
|
|
)
|
||
|
|
|
||
|
|
// GraphRecord retains original evidence IDs and payloads in each independent KB.
|
||
|
|
type GraphRecord struct {
|
||
|
|
TenantID uint64 `gorm:"primaryKey"`
|
||
|
|
KnowledgeBaseID string `gorm:"primaryKey"`
|
||
|
|
SourceTable string `gorm:"primaryKey"`
|
||
|
|
LegacyID int64 `gorm:"primaryKey;autoIncrement:false"`
|
||
|
|
GraphVersionID int64
|
||
|
|
Payload types.JSON `gorm:"type:jsonb"`
|
||
|
|
SourceSnapshotSHA256 string `gorm:"column:source_snapshot_sha256"`
|
||
|
|
ImportedAt time.Time
|
||
|
|
}
|
||
|
|
|
||
|
|
func (GraphRecord) TableName() string { return "native_graph_records" }
|
||
|
|
|
||
|
|
type GraphSource struct {
|
||
|
|
TenantID uint64 `gorm:"primaryKey"`
|
||
|
|
KnowledgeBaseID string `gorm:"primaryKey"`
|
||
|
|
SourceChunkID string `gorm:"primaryKey"`
|
||
|
|
SourceFile string
|
||
|
|
SourceContentHash string
|
||
|
|
Excerpt string
|
||
|
|
NativeKnowledgeID *string
|
||
|
|
NativeChunkID *string
|
||
|
|
NativeContentSHA256 *string `gorm:"column:native_content_sha256"`
|
||
|
|
MappingState string
|
||
|
|
}
|
||
|
|
|
||
|
|
func (GraphSource) TableName() string { return "native_graph_sources" }
|
||
|
|
|
||
|
|
func GraphTablesExist(db *gorm.DB) bool {
|
||
|
|
return db.Migrator().HasTable(&GraphRecord{}) && db.Migrator().HasTable(&GraphSource{})
|
||
|
|
}
|
||
|
|
|
||
|
|
// GraphFingerprint participates in approval conflict detection without exposing
|
||
|
|
// source paths, legacy payloads or private document identifiers to reviewers.
|
||
|
|
func GraphFingerprint(db *gorm.DB, tenant uint64, kb string) (string, error) {
|
||
|
|
if !GraphTablesExist(db) {
|
||
|
|
return "", nil
|
||
|
|
}
|
||
|
|
h := sha256.New()
|
||
|
|
count := 0
|
||
|
|
for _, item := range []struct {
|
||
|
|
model any
|
||
|
|
order string
|
||
|
|
}{
|
||
|
|
{&GraphRecord{}, "source_table, legacy_id"}, {&GraphSource{}, "source_chunk_id"},
|
||
|
|
} {
|
||
|
|
rows, err := db.Model(item.model).Where("tenant_id=? AND knowledge_base_id=?", tenant, kb).Order(item.order).Rows()
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
for rows.Next() {
|
||
|
|
var value any = &GraphRecord{}
|
||
|
|
if _, ok := item.model.(*GraphSource); ok {
|
||
|
|
value = &GraphSource{}
|
||
|
|
}
|
||
|
|
if err := db.ScanRows(rows, value); err != nil {
|
||
|
|
rows.Close()
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
if err := json.NewEncoder(h).Encode(value); err != nil {
|
||
|
|
rows.Close()
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
count++
|
||
|
|
}
|
||
|
|
err = rows.Err()
|
||
|
|
rows.Close()
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if count == 0 {
|
||
|
|
return "", nil
|
||
|
|
}
|
||
|
|
return hex.EncodeToString(h.Sum(nil)), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func DeleteGraph(db *gorm.DB, tenant uint64, kb string) error {
|
||
|
|
if !GraphTablesExist(db) {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
for _, model := range []any{&GraphSource{}, &GraphRecord{}} {
|
||
|
|
if err := db.Where("tenant_id=? AND knowledge_base_id=?", tenant, kb).Delete(model).Error; err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|