Skip to main content

grafeo_engine/database/
query.rs

1//! Query execution methods for GrafeoDB.
2
3use grafeo_common::utils::error::Result;
4
5use super::{FromValue, QueryResult};
6
7impl super::GrafeoDB {
8    /// Executes a closure with a one-shot session, syncing graph context back
9    /// to the database afterward. This ensures `USE GRAPH`, `SESSION SET GRAPH`,
10    /// and `SESSION RESET` persist across one-shot `execute()` calls.
11    fn with_session<F>(&self, func: F) -> Result<QueryResult>
12    where
13        F: FnOnce(&crate::session::Session) -> Result<QueryResult>,
14    {
15        let session = self.session();
16        let result = func(&session);
17        // Sync graph and schema state back, even on error (the session command may
18        // have succeeded before a subsequent query failed in the same session).
19        *self.current_graph.write() = session.current_graph();
20        *self.current_schema.write() = session.current_schema();
21        result
22    }
23
24    /// Runs a query directly on the database.
25    ///
26    /// A convenience method that creates a temporary session behind the
27    /// scenes. If you're running multiple queries, grab a
28    /// [`session()`](Self::session) instead to avoid the overhead.
29    ///
30    /// Graph context commands (`USE GRAPH`, `SESSION SET GRAPH`, `SESSION RESET`)
31    /// persist across calls: running `execute("USE GRAPH analytics")` followed
32    /// by `execute("MATCH (n) RETURN n")` routes the second query to the
33    /// analytics graph.
34    ///
35    /// # Errors
36    ///
37    /// Returns an error if parsing or execution fails.
38    pub fn execute(&self, query: &str) -> Result<QueryResult> {
39        self.with_session(|s| s.execute(query))
40    }
41
42    /// Executes a GQL query with visibility at the specified epoch.
43    ///
44    /// This enables time-travel queries: the query sees the database
45    /// as it existed at the given epoch.
46    ///
47    /// # Errors
48    ///
49    /// Returns an error if parsing or execution fails.
50    pub fn execute_at_epoch(
51        &self,
52        query: &str,
53        epoch: grafeo_common::types::EpochId,
54    ) -> Result<QueryResult> {
55        self.with_session(|s| s.execute_at_epoch(query, epoch))
56    }
57
58    /// Executes a query with parameters and returns the result.
59    ///
60    /// # Errors
61    ///
62    /// Returns an error if the query fails.
63    pub fn execute_with_params(
64        &self,
65        query: &str,
66        params: std::collections::HashMap<String, grafeo_common::types::Value>,
67    ) -> Result<QueryResult> {
68        self.with_session(|s| s.execute_with_params(query, params))
69    }
70
71    /// Executes a Cypher query and returns the result.
72    ///
73    /// # Errors
74    ///
75    /// Returns an error if the query fails.
76    #[cfg(feature = "cypher")]
77    pub fn execute_cypher(&self, query: &str) -> Result<QueryResult> {
78        self.with_session(|s| s.execute_cypher(query))
79    }
80
81    /// Executes a Cypher query with parameters and returns the result.
82    ///
83    /// # Errors
84    ///
85    /// Returns an error if the query fails.
86    #[cfg(feature = "cypher")]
87    pub fn execute_cypher_with_params(
88        &self,
89        query: &str,
90        params: std::collections::HashMap<String, grafeo_common::types::Value>,
91    ) -> Result<QueryResult> {
92        self.with_session(|s| s.execute_language(query, "cypher", Some(params)))
93    }
94
95    /// Executes a Gremlin query and returns the result.
96    ///
97    /// # Errors
98    ///
99    /// Returns an error if the query fails.
100    #[cfg(feature = "gremlin")]
101    pub fn execute_gremlin(&self, query: &str) -> Result<QueryResult> {
102        self.with_session(|s| s.execute_gremlin(query))
103    }
104
105    /// Executes a Gremlin query with parameters and returns the result.
106    ///
107    /// # Errors
108    ///
109    /// Returns an error if the query fails.
110    #[cfg(feature = "gremlin")]
111    pub fn execute_gremlin_with_params(
112        &self,
113        query: &str,
114        params: std::collections::HashMap<String, grafeo_common::types::Value>,
115    ) -> Result<QueryResult> {
116        self.with_session(|s| s.execute_gremlin_with_params(query, params))
117    }
118
119    /// Executes a GraphQL query and returns the result.
120    ///
121    /// # Errors
122    ///
123    /// Returns an error if the query fails.
124    #[cfg(feature = "graphql")]
125    pub fn execute_graphql(&self, query: &str) -> Result<QueryResult> {
126        self.with_session(|s| s.execute_graphql(query))
127    }
128
129    /// Executes a GraphQL query with parameters and returns the result.
130    ///
131    /// # Errors
132    ///
133    /// Returns an error if the query fails.
134    #[cfg(feature = "graphql")]
135    pub fn execute_graphql_with_params(
136        &self,
137        query: &str,
138        params: std::collections::HashMap<String, grafeo_common::types::Value>,
139    ) -> Result<QueryResult> {
140        self.with_session(|s| s.execute_graphql_with_params(query, params))
141    }
142
143    /// Executes a SQL/PGQ query (SQL:2023 GRAPH_TABLE) and returns the result.
144    ///
145    /// # Errors
146    ///
147    /// Returns an error if the query fails.
148    #[cfg(feature = "sql-pgq")]
149    pub fn execute_sql(&self, query: &str) -> Result<QueryResult> {
150        self.with_session(|s| s.execute_sql(query))
151    }
152
153    /// Executes a SQL/PGQ query with parameters and returns the result.
154    ///
155    /// # Errors
156    ///
157    /// Returns an error if the query fails.
158    #[cfg(feature = "sql-pgq")]
159    pub fn execute_sql_with_params(
160        &self,
161        query: &str,
162        params: std::collections::HashMap<String, grafeo_common::types::Value>,
163    ) -> Result<QueryResult> {
164        self.with_session(|s| s.execute_sql_with_params(query, params))
165    }
166
167    /// Executes a query in the specified language by name.
168    ///
169    /// Supported language names: `"gql"`, `"cypher"`, `"gremlin"`, `"graphql"`,
170    /// `"sparql"`, `"sql"`. Each requires the corresponding feature flag.
171    ///
172    /// # Errors
173    ///
174    /// Returns an error if the language is unknown/disabled, or if the query
175    /// fails.
176    pub fn execute_language(
177        &self,
178        query: &str,
179        language: &str,
180        params: Option<std::collections::HashMap<String, grafeo_common::types::Value>>,
181    ) -> Result<QueryResult> {
182        self.with_session(|s| s.execute_language(query, language, params))
183    }
184
185    /// Executes a query and returns a single scalar value.
186    ///
187    /// # Errors
188    ///
189    /// Returns an error if the query fails or doesn't return exactly one row.
190    pub fn query_scalar<T: FromValue>(&self, query: &str) -> Result<T> {
191        let result = self.execute(query)?;
192        result.scalar()
193    }
194}