wasccgraph_actor/
graph.rs

1use common::CAPID_GRAPHDB;
2use crate::{FromTable};
3use wasccgraph_common::{Statistics, ResultSet};
4use wasccgraph_common::protocol::*;
5use wascc_actor::{prelude::{deserialize, serialize}, untyped::{self, UntypedHostBinding}};
6
7#[doc(hidden)]
8pub struct GraphHostBindingBuilder {
9    binding: String,
10}
11
12impl GraphHostBindingBuilder {
13    pub fn graph(&self, graph: &str) -> GraphHostBinding {
14        GraphHostBinding {
15            hostbinding: untyped::host(&self.binding),
16            graph_name: graph.to_string(),
17        }
18    }
19}
20pub struct GraphHostBinding {
21    hostbinding: UntypedHostBinding,
22    graph_name: String,
23}
24
25/// Requests a named host binding. Named bindings are used when the potential
26/// exists to bind to more than one of the same capability in a single host
27pub fn host(binding: &str) -> GraphHostBindingBuilder {
28    GraphHostBindingBuilder {
29        binding: binding.to_string(),
30    }
31}
32
33/// Requests the default named host binding. Unless you know you're going to 
34/// have multiple graph providers for the same actor, you should use the
35/// default binding
36pub fn default() -> GraphHostBindingBuilder {
37    GraphHostBindingBuilder {
38        binding: "default".to_string(),
39    }
40}
41
42impl GraphHostBinding {
43    /// Executes a query against the host graph. For this provider, we assume the query is a Cypher query
44    /// but it could be Gremlin or GraphQL, etc, depending on the capability provider satisfying `wascc:graphdb`. This
45    /// can be used to perform mutations if you also return data from the mutation query
46    pub fn query<T: FromTable>(&self, query: &str) -> std::result::Result<T, Box<dyn std::error::Error>> {        
47        self.query_with_statistics(query).map(|(value, _)| value)
48    }
49
50    /// The same as [`query`](#method.query), but returns statistics from the query like execution time and nodes/relations affected, etc.
51    pub fn query_with_statistics<T:FromTable>(&self, query: &str) -> std::result::Result<(T, Statistics), Box<dyn std::error::Error>> {
52        let result_set = self.get_result_set(query).map_err(|e| format!("{}", e))?;
53        let value = T::from_table(&result_set).map_err(|e| format!("{}", e))?;
54        Ok((value, result_set.statistics))
55    }
56
57    /// Executes the given query without returning any values
58    ///
59    /// If you want to mutate the graph and retrieve values using one query, use [`query`](#method.query) instead.
60    pub fn mutate(&mut self, query: &str) -> std::result::Result<(), Box<dyn std::error::Error>> {
61        self.mutate_with_statistics(query).map(|_| ())
62    }
63
64    /// Same as [`mutate`](#method.mutate), but returns statistics about the query.
65    pub fn mutate_with_statistics(&mut self, query: &str) -> std::result::Result<Statistics, Box<dyn std::error::Error>> {        
66        let result_set = self.get_result_set(query).map_err(|e| format!("{}", e))?;
67        Ok(result_set.statistics)
68    }
69
70    /// Deletes the entire graph from the database.
71    /// 
72    /// This is a potentially very destructive function. Use with care.    
73    pub fn delete(self) -> std::result::Result<(), Box<dyn std::error::Error>> {
74        let delreq = DeleteRequest {
75            graph_name: self.graph_name.to_string()
76        };
77        self.hostbinding.call(CAPID_GRAPHDB, OP_DELETE, serialize(&delreq)?)?;
78        Ok(())        
79    }
80
81    /// Returns the name of the graph
82    pub fn name(&self) -> &str {
83        &self.graph_name
84    }
85
86    fn get_result_set(&self, query: &str) -> std::result::Result<ResultSet, Box<dyn std::error::Error>> {
87        let query = QueryRequest {
88            graph_name: self.graph_name.to_string(),
89            query: query.to_string()
90        };
91        let res = self.hostbinding.call(CAPID_GRAPHDB, OP_QUERY, serialize(&query)?)?;
92        Ok(deserialize(&res)?)        
93    }
94}