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    #[cfg(feature = "gql")]
51    pub fn execute_at_epoch(
52        &self,
53        query: &str,
54        epoch: grafeo_common::types::EpochId,
55    ) -> Result<QueryResult> {
56        self.with_session(|s| s.execute_at_epoch(query, epoch))
57    }
58
59    /// Executes a query with parameters and returns the result.
60    ///
61    /// # Errors
62    ///
63    /// Returns an error if the query fails.
64    pub fn execute_with_params(
65        &self,
66        query: &str,
67        params: std::collections::HashMap<String, grafeo_common::types::Value>,
68    ) -> Result<QueryResult> {
69        self.with_session(|s| s.execute_with_params(query, params))
70    }
71
72    /// Executes a Cypher query and returns the result.
73    ///
74    /// # Errors
75    ///
76    /// Returns an error if the query fails.
77    #[cfg(feature = "cypher")]
78    pub fn execute_cypher(&self, query: &str) -> Result<QueryResult> {
79        self.with_session(|s| s.execute_cypher(query))
80    }
81
82    /// Executes a Cypher query with parameters and returns the result.
83    ///
84    /// # Errors
85    ///
86    /// Returns an error if the query fails.
87    #[cfg(feature = "cypher")]
88    pub fn execute_cypher_with_params(
89        &self,
90        query: &str,
91        params: std::collections::HashMap<String, grafeo_common::types::Value>,
92    ) -> Result<QueryResult> {
93        self.with_session(|s| s.execute_language(query, "cypher", Some(params)))
94    }
95
96    /// Executes a Gremlin query and returns the result.
97    ///
98    /// # Errors
99    ///
100    /// Returns an error if the query fails.
101    #[cfg(feature = "gremlin")]
102    pub fn execute_gremlin(&self, query: &str) -> Result<QueryResult> {
103        self.with_session(|s| s.execute_gremlin(query))
104    }
105
106    /// Executes a Gremlin query with parameters and returns the result.
107    ///
108    /// # Errors
109    ///
110    /// Returns an error if the query fails.
111    #[cfg(feature = "gremlin")]
112    pub fn execute_gremlin_with_params(
113        &self,
114        query: &str,
115        params: std::collections::HashMap<String, grafeo_common::types::Value>,
116    ) -> Result<QueryResult> {
117        self.with_session(|s| s.execute_gremlin_with_params(query, params))
118    }
119
120    /// Executes a GraphQL query and returns the result.
121    ///
122    /// # Errors
123    ///
124    /// Returns an error if the query fails.
125    #[cfg(feature = "graphql")]
126    pub fn execute_graphql(&self, query: &str) -> Result<QueryResult> {
127        self.with_session(|s| s.execute_graphql(query))
128    }
129
130    /// Executes a GraphQL query with parameters and returns the result.
131    ///
132    /// # Errors
133    ///
134    /// Returns an error if the query fails.
135    #[cfg(feature = "graphql")]
136    pub fn execute_graphql_with_params(
137        &self,
138        query: &str,
139        params: std::collections::HashMap<String, grafeo_common::types::Value>,
140    ) -> Result<QueryResult> {
141        self.with_session(|s| s.execute_graphql_with_params(query, params))
142    }
143
144    /// Executes a SQL/PGQ query (SQL:2023 GRAPH_TABLE) and returns the result.
145    ///
146    /// # Errors
147    ///
148    /// Returns an error if the query fails.
149    #[cfg(feature = "sql-pgq")]
150    pub fn execute_sql(&self, query: &str) -> Result<QueryResult> {
151        self.with_session(|s| s.execute_sql(query))
152    }
153
154    /// Executes a SQL/PGQ query with parameters and returns the result.
155    ///
156    /// # Errors
157    ///
158    /// Returns an error if the query fails.
159    #[cfg(feature = "sql-pgq")]
160    pub fn execute_sql_with_params(
161        &self,
162        query: &str,
163        params: std::collections::HashMap<String, grafeo_common::types::Value>,
164    ) -> Result<QueryResult> {
165        self.with_session(|s| s.execute_sql_with_params(query, params))
166    }
167
168    /// Executes a query in the specified language by name.
169    ///
170    /// Supported language names: `"gql"`, `"cypher"`, `"gremlin"`, `"graphql"`,
171    /// `"sparql"`, `"sql"`. Each requires the corresponding feature flag.
172    ///
173    /// # Errors
174    ///
175    /// Returns an error if the language is unknown/disabled, or if the query
176    /// fails.
177    pub fn execute_language(
178        &self,
179        query: &str,
180        language: &str,
181        params: Option<std::collections::HashMap<String, grafeo_common::types::Value>>,
182    ) -> Result<QueryResult> {
183        self.with_session(|s| s.execute_language(query, language, params))
184    }
185
186    /// Executes a query and returns a single scalar value.
187    ///
188    /// # Errors
189    ///
190    /// Returns an error if the query fails or doesn't return exactly one row.
191    pub fn query_scalar<T: FromValue>(&self, query: &str) -> Result<T> {
192        let result = self.execute(query)?;
193        result.scalar()
194    }
195}