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}