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