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}