add not queries into uplang

somewhat awkwardly implemented as multiqueries, but hey
feat/vaults
Tomáš Mládek 2021-12-21 11:50:46 +01:00
parent 2d1a3b9ba7
commit 8e71e34a09
No known key found for this signature in database
GPG Key ID: ED21612889E75EC5
1 changed files with 32 additions and 5 deletions

View File

@ -2,7 +2,7 @@ use crate::addressing::Address;
use crate::database::entry::EntryValue;
use crate::database::inner::schema::data;
use anyhow::{anyhow, Result};
use diesel::expression::operators::{And, Or};
use diesel::expression::operators::{And, Not, Or};
use diesel::sql_types::Bool;
use diesel::sqlite::Sqlite;
use diesel::{BoxableExpression, ExpressionMethods, IntoSql, TextExpressionMethods};
@ -39,6 +39,7 @@ pub enum QueryPart {
pub enum QueryQualifier {
And,
Or,
Not,
}
#[derive(Debug)]
@ -178,12 +179,12 @@ impl TryFrom<&lexpr::Value> for Query {
"and" | "or" => {
let (cons_vec, _) = value.clone().into_vec();
let sub_expressions = &cons_vec[1..];
let values: Result<Vec<Box<Query>>> = sub_expressions
let values = sub_expressions
.iter()
.map(|value| Ok(Box::new(Query::try_from(value)?)))
.collect();
.collect::<Result<Vec<Box<Query>>>>()?;
if let Some(queries) = NonEmpty::from_vec(values?) {
if let Some(queries) = NonEmpty::from_vec(values) {
Ok(Query::MultiQuery(MultiQuery {
qualifier: match symbol.borrow() {
"and" => QueryQualifier::And,
@ -197,6 +198,25 @@ impl TryFrom<&lexpr::Value> for Query {
))
}
}
"not" => {
let (cons_vec, _) = value.clone().into_vec();
let sub_expressions = &cons_vec[1..];
let values = sub_expressions
.iter()
.map(|value| Ok(Box::new(Query::try_from(value)?)))
.collect::<Result<Vec<Box<Query>>>>()?;
if values.len() == 1 {
Ok(Query::MultiQuery(MultiQuery {
qualifier: QueryQualifier::Not,
queries: NonEmpty::from_vec(values).unwrap(),
}))
} else {
Err(anyhow!(
"Malformed expression: NOT takes exactly one parameter."
))
}
}
_ => Err(anyhow!(format!(
"Malformed expression: Unknown symbol '{}'.",
symbol
@ -287,7 +307,13 @@ impl Query {
let mut subqueries: Vec<Box<Predicate>> = subqueries?;
match subqueries.len() {
0 => Ok(Box::new(true.into_sql::<Bool>())),
1 => Ok(subqueries.remove(0)),
1 => {
if let QueryQualifier::Not = mq.qualifier {
Ok(Box::new(Not::new(subqueries.remove(0))))
} else {
Ok(subqueries.remove(0))
}
}
_ => match mq.qualifier {
QueryQualifier::And => {
let mut result: Box<And<Box<Predicate>, Box<Predicate>>> =
@ -305,6 +331,7 @@ impl Query {
}
Ok(Box::new(result))
}
QueryQualifier::Not => Err(anyhow!("NOT only takes one subquery.")),
},
}
}