ai_xiaopei
9 days ago 8de9d03cad67d6944d40567bff90350d132d60b0
internal/index/sqlite.go
@@ -6,6 +6,7 @@
   "fmt"
   "os"
   "path/filepath"
   "strings"
   _ "github.com/mattn/go-sqlite3"
   "github.com/aisim/kb-cli/internal/graph"
@@ -177,3 +178,83 @@
   return links, nil
}
// NodeInfo 节点基本信息(用于 GC)
type NodeInfo struct {
   ID   int64
   Path string
}
// GetAllNodes 获取所有节点(用于 GC 检查)
func (s *Store) GetAllNodes() ([]NodeInfo, error) {
   rows, err := s.db.Query("SELECT id, path FROM nodes")
   if err != nil {
      return nil, fmt.Errorf("查询节点失败: %w", err)
   }
   defer rows.Close()
   var nodes []NodeInfo
   for rows.Next() {
      var n NodeInfo
      if err := rows.Scan(&n.ID, &n.Path); err != nil {
         return nil, fmt.Errorf("扫描节点失败: %w", err)
      }
      nodes = append(nodes, n)
   }
   if err := rows.Err(); err != nil {
      return nil, fmt.Errorf("遍历节点失败: %w", err)
   }
   return nodes, nil
}
// DeleteNodesByPaths 删除指定路径的节点及其关联边
func (s *Store) DeleteNodesByPaths(paths []string) (int, error) {
   if len(paths) == 0 {
      return 0, nil
   }
   // 构建 IN 子句
   placeholders := make([]string, len(paths))
   args := make([]interface{}, len(paths))
   for i, path := range paths {
      placeholders[i] = "?"
      args[i] = path
   }
   tx, err := s.db.Begin()
   if err != nil {
      return 0, fmt.Errorf("开始事务失败: %w", err)
   }
   // 先删除关联边
   query := fmt.Sprintf(`
      DELETE FROM edges
      WHERE from_node IN (SELECT id FROM nodes WHERE path IN (%s))
         OR to_node IN (SELECT id FROM nodes WHERE path IN (%s))
   `, strings.Join(placeholders, ","), strings.Join(placeholders, ","))
   // 参数需要重复两次
   allArgs := append(args, args...)
   _, err = tx.Exec(query, allArgs...)
   if err != nil {
      tx.Rollback()
      return 0, fmt.Errorf("删除边失败: %w", err)
   }
   // 删除节点
   query = fmt.Sprintf("DELETE FROM nodes WHERE path IN (%s)", strings.Join(placeholders, ","))
   result, err := tx.Exec(query, args...)
   if err != nil {
      tx.Rollback()
      return 0, fmt.Errorf("删除节点失败: %w", err)
   }
   if err := tx.Commit(); err != nil {
      return 0, fmt.Errorf("提交事务失败: %w", err)
   }
   affected, _ := result.RowsAffected()
   return int(affected), nil
}