linkrs_server/graph_service/
cursor.rs1use crate::client::cursor_context::CursorPage;
2use crate::storage::{
3 StorageClient, StorageOperationContextOps, StorageSchemaContextOps, StorageSyncContextOps,
4};
5
6use super::error::GraphServiceError;
7use super::GraphService;
8
9impl<
10 S: StorageClient
11 + StorageSchemaContextOps
12 + StorageSyncContextOps
13 + StorageOperationContextOps
14 + Clone
15 + 'static,
16 > GraphService<S>
17{
18 pub async fn open_cursor(
20 &self,
21 session_id: i64,
22 stmt: &str,
23 ) -> Result<(u64, Vec<String>), String> {
24 let session = self
25 .session_manager
26 .find_session(session_id)
27 .ok_or_else(|| format!("Invalid session ID: {}", session_id))?;
28 if Self::is_command_like(stmt) {
29 return Err(
30 "Cursors support single data statements only; commands run on the materialized path"
31 .to_string(),
32 );
33 }
34 if Self::has_multiple_statements(stmt) {
35 return Err(
36 "Cursors support single data statements only; run multi-statement scripts on the materialized path"
37 .to_string(),
38 );
39 }
40 let result = self
41 .execute_stream(session_id, stmt)
42 .await
43 .map_err(|e: GraphServiceError| e.message().to_string())?;
44 let columns = result.column_names().unwrap_or_default();
45 let cursor_id = session.open_cursor(stmt.to_string(), result, columns.clone())?;
46 Ok((cursor_id, columns))
47 }
48
49 pub async fn fetch_cursor(
52 &self,
53 session_id: i64,
54 cursor_id: u64,
55 page_size: usize,
56 ) -> Result<CursorPage, String> {
57 let session = self
58 .session_manager
59 .find_session(session_id)
60 .ok_or_else(|| format!("Invalid session ID: {}", session_id))?;
61 tokio::task::spawn_blocking(move || session.fetch_cursor_page(cursor_id, page_size))
62 .await
63 .map_err(|e| format!("Cursor fetch task failed: {e}"))?
64 }
65
66 pub async fn close_cursor(&self, session_id: i64, cursor_id: u64) -> Result<bool, String> {
68 let session = self
69 .session_manager
70 .find_session(session_id)
71 .ok_or_else(|| format!("Invalid session ID: {}", session_id))?;
72 Ok(session.close_cursor(cursor_id))
73 }
74}