use crate::connection::Session;
use crate::error::{Error, Result};
use graphlite::QueryResult;
pub struct QueryBuilder<'session> {
session: &'session Session,
match_patterns: Vec<String>,
where_clauses: Vec<String>,
with_clauses: Vec<String>,
return_clause: Option<String>,
order_by: Option<String>,
skip: Option<usize>,
limit: Option<usize>,
}
impl<'session> QueryBuilder<'session> {
pub(crate) fn new(session: &'session Session) -> Self {
QueryBuilder {
session,
match_patterns: Vec::new(),
where_clauses: Vec::new(),
with_clauses: Vec::new(),
return_clause: None,
order_by: None,
skip: None,
limit: None,
}
}
pub fn match_pattern(mut self, pattern: &str) -> Self {
self.match_patterns.push(pattern.to_string());
self
}
pub fn where_clause(mut self, condition: &str) -> Self {
self.where_clauses.push(condition.to_string());
self
}
pub fn with_clause(mut self, clause: &str) -> Self {
self.with_clauses.push(clause.to_string());
self
}
pub fn return_clause(mut self, clause: &str) -> Self {
self.return_clause = Some(clause.to_string());
self
}
pub fn order_by(mut self, clause: &str) -> Self {
self.order_by = Some(clause.to_string());
self
}
pub fn skip(mut self, n: usize) -> Self {
self.skip = Some(n);
self
}
pub fn limit(mut self, n: usize) -> Self {
self.limit = Some(n);
self
}
pub fn build(&self) -> Result<String> {
let mut query = String::new();
if !self.match_patterns.is_empty() {
for pattern in &self.match_patterns {
if !query.is_empty() {
query.push(' ');
}
query.push_str("MATCH ");
query.push_str(pattern);
}
}
if !self.where_clauses.is_empty() {
query.push_str(" WHERE ");
query.push_str(&self.where_clauses.join(" AND "));
}
for with_clause in &self.with_clauses {
query.push_str(" WITH ");
query.push_str(with_clause);
}
if let Some(ref return_clause) = self.return_clause {
query.push_str(" RETURN ");
query.push_str(return_clause);
} else if !self.match_patterns.is_empty() {
return Err(Error::InvalidOperation(
"MATCH query requires a RETURN clause".to_string(),
));
}
if let Some(ref order_by) = self.order_by {
query.push_str(" ORDER BY ");
query.push_str(order_by);
}
if let Some(skip) = self.skip {
query.push_str(&format!(" SKIP {}", skip));
}
if let Some(limit) = self.limit {
query.push_str(&format!(" LIMIT {}", limit));
}
Ok(query.trim().to_string())
}
pub fn execute(&self) -> Result<QueryResult> {
let query = self.build()?;
self.session.query(&query)
}
}
impl<'session> Session {
pub fn query_builder(&self) -> QueryBuilder<'_> {
QueryBuilder::new(self)
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_query_builder_types_compile() {
}
}