use crate::error::StorageError;
use crate::storage::DbPool;
#[derive(Debug, Clone)]
pub struct NewEdge {
pub source_node_id: i64,
pub target_node_id: i64,
pub edge_type: String,
pub edge_label: Option<String>,
pub source_chunk_id: Option<i64>,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct NoteEdge {
pub id: i64,
pub account_id: String,
pub source_node_id: i64,
pub target_node_id: i64,
pub edge_type: String,
pub edge_label: Option<String>,
pub source_chunk_id: Option<i64>,
pub created_at: String,
}
type NoteEdgeRow = (
i64,
String,
i64,
i64,
String,
Option<String>,
Option<i64>,
String,
);
impl NoteEdge {
fn from_row(r: NoteEdgeRow) -> Self {
Self {
id: r.0,
account_id: r.1,
source_node_id: r.2,
target_node_id: r.3,
edge_type: r.4,
edge_label: r.5,
source_chunk_id: r.6,
created_at: r.7,
}
}
}
pub async fn delete_edges_for_source(
pool: &DbPool,
account_id: &str,
source_node_id: i64,
) -> Result<u64, StorageError> {
let result = sqlx::query("DELETE FROM note_edges WHERE account_id = ? AND source_node_id = ?")
.bind(account_id)
.bind(source_node_id)
.execute(pool)
.await
.map_err(|e| StorageError::Query { source: e })?;
Ok(result.rows_affected())
}
pub async fn insert_edge(
pool: &DbPool,
account_id: &str,
edge: &NewEdge,
) -> Result<(), StorageError> {
sqlx::query(
"INSERT OR IGNORE INTO note_edges \
(account_id, source_node_id, target_node_id, edge_type, edge_label, source_chunk_id) \
VALUES (?, ?, ?, ?, ?, ?)",
)
.bind(account_id)
.bind(edge.source_node_id)
.bind(edge.target_node_id)
.bind(&edge.edge_type)
.bind(&edge.edge_label)
.bind(edge.source_chunk_id)
.execute(pool)
.await
.map_err(|e| StorageError::Query { source: e })?;
Ok(())
}
pub async fn insert_edges(
pool: &DbPool,
account_id: &str,
edges: &[NewEdge],
) -> Result<(), StorageError> {
for edge in edges {
insert_edge(pool, account_id, edge).await?;
}
Ok(())
}
pub async fn get_edges_for_source(
pool: &DbPool,
account_id: &str,
source_node_id: i64,
) -> Result<Vec<NoteEdge>, StorageError> {
let rows: Vec<NoteEdgeRow> = sqlx::query_as(
"SELECT id, account_id, source_node_id, target_node_id, \
edge_type, edge_label, source_chunk_id, created_at \
FROM note_edges \
WHERE account_id = ? AND source_node_id = ? \
ORDER BY id",
)
.bind(account_id)
.bind(source_node_id)
.fetch_all(pool)
.await
.map_err(|e| StorageError::Query { source: e })?;
Ok(rows.into_iter().map(NoteEdge::from_row).collect())
}
pub async fn get_edges_for_target(
pool: &DbPool,
account_id: &str,
target_node_id: i64,
) -> Result<Vec<NoteEdge>, StorageError> {
let rows: Vec<NoteEdgeRow> = sqlx::query_as(
"SELECT id, account_id, source_node_id, target_node_id, \
edge_type, edge_label, source_chunk_id, created_at \
FROM note_edges \
WHERE account_id = ? AND target_node_id = ? \
ORDER BY id",
)
.bind(account_id)
.bind(target_node_id)
.fetch_all(pool)
.await
.map_err(|e| StorageError::Query { source: e })?;
Ok(rows.into_iter().map(NoteEdge::from_row).collect())
}