Skip to content

Commit

Permalink
Documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Threated committed Jun 13, 2022
1 parent 35f606d commit bbba07a
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/aio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{types::GraphQuery, FromGraphValue, GraphResponse, query};


pub trait AsyncGraphCommands: ConnectionLike + Send + Sized {
///
fn graph_query<'a, Q, RT>(
&'a mut self,
graph: &'a str,
Expand Down
24 changes: 22 additions & 2 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ macro_rules! apply_macro {

pub(crate) use apply_macro;

/// So you dont have to write FromGraphValue::from_graph_value(value) every time
/// Shorthand for FromGraphValue::from_graph_value(value)
#[inline(always)]
pub fn from_graph_value<T: FromGraphValue>(value: GraphValue) -> RedisResult<T> {
FromGraphValue::from_graph_value(value)
}

/// Helper for creating Rediserror
/// Helper for creating a Rediserror
pub fn create_rediserror(desc: &str) -> RedisError {
(
ErrorKind::TypeError,
Expand All @@ -29,6 +29,26 @@ pub fn create_rediserror(desc: &str) -> RedisError {
).into()
}

/// Macro for creating a GraphQuery
/// ## Diffrent usecases
/// ```
/// query!("query string"); // Normal query
/// query!("query string", true) // Normal read only query
/// query!(
/// "query string $param",
/// {
/// 'param' => 5 // or "Some string" or 4.8 everything is converted with Parameter::from
/// }
/// ) // Query with parameters and read only
/// query!(
/// "query string $param $name",
/// {
/// 'param' => 5,
/// 'name' => 'username'
/// },
/// true
/// ) // Query with parameters and read only
/// ```
#[macro_export]
macro_rules! query {
( $s:expr $(, $ro:literal)?) => {{
Expand Down
33 changes: 32 additions & 1 deletion src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
helpers::{create_rediserror, apply_macro}
};

/// Official enum from redis-graph https://github.com/RedisGraph/RedisGraph/blob/master/src/resultset/formatters/resultset_formatter.h#L20-L33
/// [Official enum](https://github.com/RedisGraph/RedisGraph/blob/master/src/resultset/formatters/resultset_formatter.h#L20-L33) from redis-graph
mod types {
pub const VALUE_UNKNOWN: i64 = 0;
pub const VALUE_NULL: i64 = 1;
Expand All @@ -26,6 +26,7 @@ mod types {
pub const VALUE_POINT: i64 = 11;
}

/// An enum containing every possible type that can be returned by redisgraph
#[derive(Clone, Debug, PartialEq)]
pub enum GraphValue {
Unknown(Value),
Expand All @@ -42,12 +43,14 @@ pub enum GraphValue {
Null,
}

/// The type returned by the point method in cypher
#[derive(Debug, Clone, PartialEq)]
pub struct GeoPoint {
pub latitude: f32,
pub longitude: f32,
}

/// Map typed as returned by RETURN {a: 1}
#[derive(Debug, Clone, PartialEq)]
pub struct GraphMap(pub HashMap<String, GraphValue>);

Expand Down Expand Up @@ -138,6 +141,8 @@ pub trait PropertyAccess {
}
}

/// gets a property by its order of definition
/// Note when relying on property order make sure every CREATE has the same order of these properties
fn get_property_by_index<T: FromGraphValue>(&self, idx: usize) -> RedisResult<T> {
from_graph_value(self.properties()[idx].clone())
}
Expand Down Expand Up @@ -179,12 +184,38 @@ impl PropertyAccess for Relationship {
}
}

/// Type for graph paths as returned by MATCH p=(\:A)-[\:B]->(\:C) RETURN p
#[derive(Debug, PartialEq, Clone)]
pub struct GraphPath {
pub nodes: Vec<Node>,
pub relationships: Vec<Relationship>,
}

/// ## Overview
/// Trait for converting the response to an arbitray type which implents it
/// This is similar to the FromRedisValue trait from redis
///
/// ## Example
/// ```no_run
/// struct MyType {
/// a: i32
/// b: Vec<String>
/// }
///
/// impl FromGraphValue for MyType {
/// fn from_graph_value(value: GraphValue) -> RedisResult<Self> {
/// let (a, b): (i32, Vec<String>) = from_graph_value(value)?;
/// // You dont even need the type annotations above as they are inferred in this case
/// Ok(MyType {
/// a,
/// b
/// })
/// }
/// }
/// // Now you can write code like this
/// let con = // Connection to redis
/// let data: Vec<MyType> = con.graph_query("graphname", query!("RETURN 1, ['a', 'b']"))?.data;
/// ```
pub trait FromGraphValue: Sized {
fn from_graph_value(value: GraphValue) -> RedisResult<Self>;
}
Expand Down
4 changes: 2 additions & 2 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ test_parse! {point,
#[test]
fn test_parse_graphtypes() {
let con = &mut sync_con();
con.graph_query::<_, ()>("test", query!("Create (:User {a: 1})-[:follows]->(:User)"))
con.graph_query_void("test", query!("Create (:User {a: 1})-[:follows]->(:User)"))
.unwrap();
let paths: Vec<(GraphPath,)> = con
.graph_query(
Expand All @@ -207,7 +207,7 @@ fn test_parse_graphtypes() {
assert_eq!(relationships[0].get_property_by_index::<i32>(0).unwrap(), 3);
}

con.graph_query::<_, ()>(
con.graph_query_void(
"test",
query!("Match (a:User {a: 1})-[:follows]->(b:User) Detach Delete a, b"),
)
Expand Down
22 changes: 22 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,26 @@ use redis::{FromRedisValue, Value, RedisResult, from_redis_value};

use crate::{GraphValue, helpers::{create_rediserror, apply_macro}, FromGraphValue, from_graph_value};

/// ## Overview
/// Response type from redis graph
/// This type is generic over the a type that should represent the return value of each match in the query
/// For example a query like:
/// MATCH (a\:User {name\: 'You'}) RETURN a
/// Will return a Vec of whatever stands in the return clause
/// but the generic type in this case should not be `Node` it should be `(Node,)`
/// as there can be multiple comma seperated items returned
#[derive(Debug)]
pub struct GraphResponse<T = GraphValue> where T: FromGraphValue {
/// List of return type names e.g. RETURN item, otheritem
/// will result in vec!["item", "otheritem"]
/// This info is largely useless
pub header: Vec<String>,
/// Every item of data represents one match of a request
/// each T is than the type returned by the return clause which is always a tuple-
/// Even for RETURN 1 should be (i32, ) not i32 as there can always be multiple items
/// returned from a single return clause
pub data: Vec<T>,
/// Statistics of the query e.g. "Cached execution: 1" or "Query internal execution time: 0.01337 milliseconds"
pub statistics: Vec<String>
}

Expand All @@ -22,6 +38,7 @@ impl<T: FromGraphValue> GraphResponse<T> {
).collect()
}

/// Parses a `redis::Value` into a `RedisResult<GraphResponse<T>>`
pub fn parse_response(value: &Value) -> RedisResult<GraphResponse<T>> {
match value {
Value::Bulk(ref values) => {
Expand Down Expand Up @@ -57,6 +74,8 @@ impl<T: FromGraphValue> FromRedisValue for GraphResponse<T> {
}
}

/// Contains information for constructing the query.
/// Primarily generated by the `query!` macro
#[derive(PartialEq, Debug)]
pub struct GraphQuery {
pub query: &'static str,
Expand Down Expand Up @@ -109,6 +128,9 @@ impl From<&'static str> for GraphQuery {
}
}

/// Used for inserting user data in the query and escaping it properly
/// This type gets primarilly constructed by the `query!` macro but can
/// also be constructed with `Parameter::from`
#[derive(Clone, PartialEq, Debug)]
pub enum Parameter {
String(String),
Expand Down

0 comments on commit bbba07a

Please sign in to comment.