Skip to content

Commit

Permalink
wip reutrn
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandre-ricciardi committed Jun 3, 2024
1 parent c8f3ec2 commit c3bed68
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 242 deletions.
14 changes: 11 additions & 3 deletions lib/zawgl-cypher-query-model/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use model::{EvalScopeClause, WhereClause};
use model::{EvalResultItem, EvalScopeClause, WhereClause};
use zawgl_core::model::PropertyGraph;

pub mod model;
Expand Down Expand Up @@ -30,7 +30,7 @@ pub mod parameters;

#[derive(Clone)]
pub enum StepType {
MATCH, CREATE, DELETE, WHERE, WITH(EvalScopeClause)
MATCH, CREATE, DELETE, WHERE, WITH(EvalScopeClause), RETURN(EvalScopeClause)
}

#[derive(Clone)]
Expand All @@ -51,5 +51,13 @@ impl QueryStep {
}

pub struct QueryResult {
pub patterns: Vec<PropertyGraph>,
pub matched_graphs: Vec<PropertyGraph>,
pub return_eval: Vec::<Vec<EvalResultItem>>,
}

impl QueryResult {
pub fn new(matched_graphs: Vec<PropertyGraph>, return_eval: Vec::<Vec<EvalResultItem>>) -> Self {
QueryResult{matched_graphs, return_eval}
}

}
4 changes: 1 addition & 3 deletions lib/zawgl-cypher-query-model/src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ pub enum EvalResultItem {
String(StringResult),
}


#[derive(Debug, Clone)]
pub struct EvalItem {
pub item: ValueItem,
Expand Down Expand Up @@ -222,12 +221,11 @@ pub struct BoolCondition {

pub struct Request {
pub steps: Vec<QueryStep>,
pub return_clause: Option<EvalScopeClause>,
}

impl Request {
pub fn new() -> Self {
Request {steps: Vec::new(), return_clause: None}
Request {steps: Vec::new()}
}
}

Expand Down
20 changes: 8 additions & 12 deletions lib/zawgl-front/src/cypher/query_engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,6 @@ impl AstVisitor for CypherAstVisitor {
}
fn enter_return(&mut self) -> AstVisitorResult {
self.set_visitor_state(VisitorState::ReturnClause);
if let Some(request) = &mut self.request {
request.return_clause = Some(EvalScopeClause::new());
}
Ok(())
}
fn enter_where(&mut self, node: &AstTagNode) -> AstVisitorResult {
Expand All @@ -182,9 +179,7 @@ impl AstVisitor for CypherAstVisitor {
}
fn enter_function(&mut self) -> AstVisitorResult {
if let Some(request) = &mut self.request {
if let Some(_) = &mut request.return_clause {
self.push_visitor_state(VisitorState::FunctionCall);
}
self.push_visitor_state(VisitorState::FunctionCall);
}
Ok(())
}
Expand Down Expand Up @@ -364,7 +359,7 @@ impl AstVisitor for CypherAstVisitor {
fn exit_query(&mut self) -> AstVisitorResult { Ok(())}
fn exit_return(&mut self) -> AstVisitorResult {
if let Some(req) = &mut self.request {
req.return_clause = Some(EvalScopeClause::new_expression(self.var_scope_filter.clone()));
req.steps.push(QueryStep::new(StepType::RETURN(EvalScopeClause::new_expression(self.var_scope_filter.clone()))))
}
Ok(())
}
Expand Down Expand Up @@ -631,11 +626,12 @@ mod test_query_engine {
assert_eq!(rel.get_var(), &Some(String::from("r")));
assert_eq!(rel.get_labels_ref()[0], String::from("PLAYED_IN"));
assert_eq!(rel.get_status(), &Status::Match);
let ret = req.return_clause.as_ref().expect("return clause").expressions.first().expect("a return function with alias");
if let EvalScopeExpression::FunctionCall(func) = ret {
assert_eq!(func.alias, Some("total".to_string()));
assert_eq!(func.name, "sum".to_string());
assert_eq!(func.args.len(), 1);
if let StepType::RETURN(eval) = &req.steps.last().expect("return clause").step_type {
if let EvalScopeExpression::FunctionCall(func) = eval.expressions.first().expect("a return function with alias") {
assert_eq!(func.alias, Some("total".to_string()));
assert_eq!(func.name, "sum".to_string());
assert_eq!(func.args.len(), 1);
}
}
} else {
assert!(false, "no request found");
Expand Down
172 changes: 48 additions & 124 deletions lib/zawgl-front/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use std::{collections::{HashMap, hash_map::Entry}, slice::Iter};
use bson::{Bson, Document, doc};
use cypher::query_engine::{process_cypher_query, CypherError};
use zawgl_core::{model::{Property, PropertyValue, PropertyGraph, Relationship, Node}, graph::{EdgeData, NodeIndex, EdgeIndex}};
use zawgl_cypher_query_model::{parameters::build_parameters, model::{Request, EvalScopeExpression, ValueItem}};
use zawgl_cypher_query_model::{model::{EvalScopeClause, EvalScopeExpression, Request, ValueItem}, parameters::build_parameters, QueryResult, StepType};
use tx_handler::{handle_graph_request, request_handler::RequestHandler, handler::TxHandler, DatabaseError};

extern crate zawgl_core;
Expand All @@ -44,10 +44,10 @@ pub fn handle_open_cypher_request(tx_handler: TxHandler, graph_request_handler:
let request = process_cypher_query(query, params);
match request {
Ok(r) => {
let matched_graphs = handle_graph_request(tx_handler, graph_request_handler.clone(), r.steps.to_vec(), None);
match matched_graphs {
Ok(mg) => {
build_response(request_id, mg, &r)
let oqr = handle_graph_request(tx_handler, graph_request_handler.clone(), r.steps.to_vec(), None);
match oqr {
Ok(qr) => {
build_response(request_id, qr, &r)
},
Err(e) => {
graph_request_handler.lock().unwrap().cancel();
Expand All @@ -72,18 +72,32 @@ fn build_cypher_error(request_id: &str, err: CypherError) -> Result<Document, Cy
response_doc.insert("error", format!("database error {}", err));
Ok(response_doc)
}
fn build_response(request_id: &str, matched_graphs: Vec<PropertyGraph>, request: &Request) -> Result<Document, CypherError> {

fn get_return_clause(request: &Request) -> Option<&EvalScopeClause> {
request.steps.last().and_then(|ret| {
match &ret.step_type {
StepType::RETURN(ret_clause) => Some(ret_clause),
_ => None
}
})
}

fn build_response(request_id: &str, qr: QueryResult, request: &Request) -> Result<Document, CypherError> {
let mut result_doc = Document::new();
let mut graph_list = Vec::new();

if let Some(ret) = &request.return_clause {
let wildcard = ret.has_wildcard();
for pattern in &matched_graphs {
let mut graph_doc = Document::new();
let mut nodes_doc = Vec::new();
let mut rels_doc = Vec::new();

for ret_exp in &ret.expressions {
let return_wildcard = request.steps.last().map(|ret| {
match ret.step_type {
StepType::RETURN(ret_clause) => ret_clause.has_wildcard(),
_ => false
}
});
let wildcard = return_wildcard == Some(true);
for pattern in &qr.matched_graphs {
let mut graph_doc = Document::new();
let mut nodes_doc = Vec::new();
let mut rels_doc = Vec::new();
if let Some(ret_clause) = get_return_clause(request) {
for ret_exp in &ret_clause.expressions {
match ret_exp {
EvalScopeExpression::Item(item) => {
match &item.item {
Expand All @@ -97,123 +111,33 @@ fn build_response(request_id: &str, matched_graphs: Vec<PropertyGraph>, request:
_ => {}
}
}

if !nodes_doc.is_empty() {
graph_doc.insert("nodes", nodes_doc);
}
if !rels_doc.is_empty() {
graph_doc.insert("relationships", rels_doc);
}
if !graph_doc.is_empty() {
graph_list.push(graph_doc);
}
}

let mut grouping = Vec::new();
for ret_exp in &ret.expressions {
match ret_exp {
EvalScopeExpression::Item(item) => {
match &item.item {
ValueItem::ItemPropertyName(prop_name) => {
grouping.push(&prop_name.item_name);
},
ValueItem::NamedItem(named_item) => {
grouping.push(named_item);
}
}
},
_ => {}
}

if !nodes_doc.is_empty() {
graph_doc.insert("nodes", nodes_doc);
}

let mut combinations = vec![];
let mut curr_items = vec![];
for graph in &matched_graphs {
build_items_combinations(grouping.iter(), &graph, &mut combinations, &mut curr_items)?;
if !rels_doc.is_empty() {
graph_doc.insert("relationships", rels_doc);
}

let mut values_doc = vec![];

let mut aggregations = HashMap::new();

for combination in &combinations {
let ids = combination.get_item_ids();
if let Entry::Vacant(e) = aggregations.entry(ids) {
e.insert(vec![combination]);
} else {
let idsref = combination.get_item_ids();
aggregations.get_mut(&idsref).unwrap().push(combination);
}
if !graph_doc.is_empty() {
graph_list.push(graph_doc);
}
}




for combinations in aggregations.values() {
let mut row = vec![];
if let Some(combination) = combinations.first() {
let items = combination.get_items();
for ret_exp in &ret.expressions {
match ret_exp {
EvalScopeExpression::Item(ret_item) => {
match &ret_item.item {
ValueItem::ItemPropertyName(prop_name) => {
row.push(get_property_in_items(ret_item.alias.as_ref(), &prop_name.item_name, &prop_name.property_name, items)?);
},
ValueItem::NamedItem(named_item) => {
for item in &combination.items {
match item {
Item::Node(n) => {
if let Some(var) = n.get_var() {
if var == named_item {
row.push(make_node_doc(ret_item.alias.as_ref(), &named_item, n)?);
}
}
},
Item::Relationship(rel) => {
if let Some(var) = rel.relationship.get_var() {
if var == named_item {
row.push(make_relationship_doc(ret_item.alias.as_ref(), &named_item, rel, combination.graph)?);
}
}
}
}
}
}
}
},
_ => {}
}
}
}

let graphs = combinations.iter().map(|c| c.graph).collect::<Vec<&PropertyGraph>>();
for ret_exp in &ret.expressions {
match ret_exp {
EvalScopeExpression::FunctionCall(fun) => {
let ret_name = if let Some(a) = &fun.alias {
a.to_string()
} else {
"sum".to_string()
};
match fun.name.as_str() {
"sum" => {
let sum = compute_sum(&fun.args, &graphs);
row.push(doc! {ret_name: sum});
},
_ => {}
}
},
_ => {}
}
}
values_doc.push(row);
let mut values_doc = vec![];
for res in qr.return_eval {
let mut row = vec![];
for item in res {
row.push(value)
}
values_doc.push(row);
}


if !values_doc.is_empty() {
result_doc.insert("values", values_doc);
}
if !values_doc.is_empty() {
result_doc.insert("values", values_doc);
}

if !graph_list.is_empty() {
result_doc.insert("graphs", graph_list);
}
Expand Down
Loading

0 comments on commit c3bed68

Please sign in to comment.