refactoring: remove query_entries(), from_sexp into TryFrom, query_to_sqlite is a method
This commit is contained in:
parent
4c1034ee4b
commit
5096e1eece
3 changed files with 199 additions and 239 deletions
401
src/database.rs
401
src/database.rs
|
@ -11,6 +11,7 @@ use diesel::r2d2::{self, ConnectionManager};
|
||||||
use diesel::sql_types::Bool;
|
use diesel::sql_types::Bool;
|
||||||
use diesel::sqlite::{Sqlite, SqliteConnection};
|
use diesel::sqlite::{Sqlite, SqliteConnection};
|
||||||
use lexpr::value::Value::Symbol;
|
use lexpr::value::Value::Symbol;
|
||||||
|
use lexpr::Value;
|
||||||
use lexpr::Value::Cons;
|
use lexpr::Value::Cons;
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use nonempty::NonEmpty;
|
use nonempty::NonEmpty;
|
||||||
|
@ -275,17 +276,99 @@ pub enum Query {
|
||||||
MultiQuery(MultiQuery),
|
MultiQuery(MultiQuery),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Query {
|
type Predicate = dyn BoxableExpression<data::table, Sqlite, SqlType = Bool>;
|
||||||
pub fn from_sexp(expression: &lexpr::Value) -> Result<Self> {
|
|
||||||
|
impl TryFrom<&lexpr::Value> for Query {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(expression: &Value) -> Result<Self> {
|
||||||
|
fn parse_component<T: FromStr>(value: &lexpr::Value) -> Result<QueryComponent<T>>
|
||||||
|
where
|
||||||
|
<T as FromStr>::Err: std::fmt::Debug,
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
Cons(cons) => {
|
||||||
|
if let Symbol(symbol) = cons.car() {
|
||||||
|
match symbol.borrow() {
|
||||||
|
"in" => {
|
||||||
|
let (cons_vec, _) = cons.clone().into_vec();
|
||||||
|
if let Some(split) = cons_vec.split_first() {
|
||||||
|
let args = split.1;
|
||||||
|
let values: Result<Vec<T>, _> = args.iter().map(|value| {
|
||||||
|
if let lexpr::Value::String(str) = value {
|
||||||
|
match T::from_str(str.borrow()) {
|
||||||
|
Ok(value) => Ok(value),
|
||||||
|
Err(error) => Err(anyhow!(format!("Malformed expression: Conversion of inner value '{}' from string failed: {:#?}",str, error))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("Malformed expression: Inner value list must be comprised of strings."))
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
Ok(QueryComponent::In(values?))
|
||||||
|
} else {
|
||||||
|
Err(anyhow!(
|
||||||
|
"Malformed expression: Inner value cannot be empty."
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"contains" => {
|
||||||
|
let (mut cons_vec, _) = cons.clone().into_vec();
|
||||||
|
match cons_vec.len() {
|
||||||
|
2 => {
|
||||||
|
let value = cons_vec.remove(1);
|
||||||
|
if let lexpr::Value::String(str) = value {
|
||||||
|
Ok(QueryComponent::Contains(str.into_string()))
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("Malformed expression: 'Contains' argument must be a string."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(anyhow!(
|
||||||
|
"Malformed expression: 'Contains' requires a single argument."
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(anyhow!(format!(
|
||||||
|
"Malformed expression: Unknown symbol {}",
|
||||||
|
symbol
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(anyhow!(format!(
|
||||||
|
"Malformed expression: Inner value '{:?}' is not a symbol.",
|
||||||
|
value
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lexpr::Value::String(str) => match T::from_str(str.borrow()) {
|
||||||
|
Ok(value) => Ok(QueryComponent::Exact(value)),
|
||||||
|
Err(error) => Err(anyhow!(format!(
|
||||||
|
"Malformed expression: Conversion of inner value '{}' from string failed: {:#?}",
|
||||||
|
str, error
|
||||||
|
))),
|
||||||
|
},
|
||||||
|
lexpr::Value::Symbol(symbol) => match symbol.borrow() {
|
||||||
|
"?" => Ok(QueryComponent::Any),
|
||||||
|
_ => Err(anyhow!(format!(
|
||||||
|
"Malformed expression: Unknown symbol {}",
|
||||||
|
symbol
|
||||||
|
))),
|
||||||
|
},
|
||||||
|
_ => Err(anyhow!(
|
||||||
|
"Malformed expression: Inner value not a string, list or '?'."
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Cons(value) = expression {
|
if let Cons(value) = expression {
|
||||||
if let Symbol(symbol) = value.car() {
|
if let Symbol(symbol) = value.car() {
|
||||||
match symbol.borrow() {
|
match symbol.borrow() {
|
||||||
"matches" => {
|
"matches" => {
|
||||||
let (cons_vec, _) = value.clone().into_vec();
|
let (cons_vec, _) = value.clone().into_vec();
|
||||||
if let [_, entity, attribute, value] = &cons_vec[..] {
|
if let [_, entity, attribute, value] = &cons_vec[..] {
|
||||||
let entity = Query::parse_component::<Address>(entity)?;
|
let entity = parse_component::<Address>(entity)?;
|
||||||
let attribute = Query::parse_component::<String>(attribute)?;
|
let attribute = parse_component::<String>(attribute)?;
|
||||||
let value = Query::parse_component::<EntryValue>(value)?;
|
let value = parse_component::<EntryValue>(value)?;
|
||||||
Ok(Query::SingleQuery(QueryPart::Matches(EntryQuery {
|
Ok(Query::SingleQuery(QueryPart::Matches(EntryQuery {
|
||||||
entity,
|
entity,
|
||||||
attribute,
|
attribute,
|
||||||
|
@ -320,7 +403,7 @@ impl Query {
|
||||||
let sub_expressions = &cons_vec[1..];
|
let sub_expressions = &cons_vec[1..];
|
||||||
let values: Result<Vec<Box<Query>>> = sub_expressions
|
let values: Result<Vec<Box<Query>>> = sub_expressions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|value| Ok(Box::new(Query::from_sexp(value)?)))
|
.map(|value| Ok(Box::new(Query::try_from(value)?)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let Some(queries) = NonEmpty::from_vec(values?) {
|
if let Some(queries) = NonEmpty::from_vec(values?) {
|
||||||
|
@ -352,82 +435,103 @@ impl Query {
|
||||||
Err(anyhow!("Malformed expression: Not a list."))
|
Err(anyhow!("Malformed expression: Not a list."))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_component<T: FromStr>(value: &lexpr::Value) -> Result<QueryComponent<T>>
|
impl Query {
|
||||||
where
|
fn to_sqlite_predicates(&self) -> Result<Box<Predicate>> {
|
||||||
<T as FromStr>::Err: std::fmt::Debug,
|
match self {
|
||||||
{
|
Query::SingleQuery(qp) => match qp {
|
||||||
match value {
|
QueryPart::Matches(eq) => {
|
||||||
Cons(cons) => {
|
let mut subqueries: Vec<Box<Predicate>> = vec![];
|
||||||
if let Symbol(symbol) = cons.car() {
|
|
||||||
match symbol.borrow() {
|
|
||||||
"in" => {
|
|
||||||
let (cons_vec, _) = cons.clone().into_vec();
|
|
||||||
if let Some(split) = cons_vec.split_first() {
|
|
||||||
let args = split.1;
|
|
||||||
let values: Result<Vec<T>, _> = args.iter().map(|value| {
|
|
||||||
if let lexpr::Value::String(str) = value {
|
|
||||||
match T::from_str(str.borrow()) {
|
|
||||||
Ok(value) => Ok(value),
|
|
||||||
Err(error) => Err(anyhow!(format!("Malformed expression: Conversion of inner value '{}' from string failed: {:#?}",str, error))),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(anyhow!("Malformed expression: Inner value list must be comprised of strings."))
|
|
||||||
}
|
|
||||||
}).collect();
|
|
||||||
|
|
||||||
Ok(QueryComponent::In(values?))
|
match &eq.entity {
|
||||||
} else {
|
QueryComponent::Exact(q_target) => {
|
||||||
Err(anyhow!(
|
subqueries.push(Box::new(data::target.eq(q_target.encode()?)))
|
||||||
"Malformed expression: Inner value cannot be empty."
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"contains" => {
|
QueryComponent::In(q_targets) => {
|
||||||
let (mut cons_vec, _) = cons.clone().into_vec();
|
let targets: Result<Vec<_>, _> =
|
||||||
match cons_vec.len() {
|
q_targets.iter().map(|t| t.encode()).collect();
|
||||||
2 => {
|
subqueries.push(Box::new(data::target.eq_any(targets?)))
|
||||||
let value = cons_vec.remove(1);
|
}
|
||||||
if let lexpr::Value::String(str) = value {
|
QueryComponent::Contains(_) => {
|
||||||
Ok(QueryComponent::Contains(str.into_string()))
|
return Err(anyhow!("Addresses cannot be queried alike."))
|
||||||
} else {
|
}
|
||||||
Err(anyhow!("Malformed expression: 'Contains' argument must be a string."))
|
QueryComponent::Any => {}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
_ => Err(anyhow!(
|
match &eq.attribute {
|
||||||
"Malformed expression: 'Contains' requires a single argument."
|
QueryComponent::Exact(q_key) => {
|
||||||
)),
|
subqueries.push(Box::new(data::key.eq(q_key.clone())))
|
||||||
}
|
}
|
||||||
|
QueryComponent::In(q_keys) => {
|
||||||
|
subqueries.push(Box::new(data::key.eq_any(q_keys.clone())))
|
||||||
|
}
|
||||||
|
QueryComponent::Contains(q_key) => {
|
||||||
|
subqueries.push(Box::new(data::key.like(format!("%{}%", q_key))))
|
||||||
|
}
|
||||||
|
QueryComponent::Any => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
match &eq.value {
|
||||||
|
QueryComponent::Exact(q_value) => {
|
||||||
|
subqueries.push(Box::new(data::value.eq(q_value.to_string()?)))
|
||||||
|
}
|
||||||
|
QueryComponent::In(q_values) => {
|
||||||
|
let values: Result<Vec<_>, _> =
|
||||||
|
q_values.iter().map(|v| v.to_string()).collect();
|
||||||
|
subqueries.push(Box::new(data::value.eq_any(values?)))
|
||||||
|
}
|
||||||
|
QueryComponent::Contains(q_value) => {
|
||||||
|
subqueries.push(Box::new(data::value.like(format!("%{}%", q_value))))
|
||||||
|
}
|
||||||
|
QueryComponent::Any => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
match subqueries.len() {
|
||||||
|
0 => Ok(Box::new(true.into_sql::<Bool>())),
|
||||||
|
1 => Ok(subqueries.remove(0)),
|
||||||
|
_ => {
|
||||||
|
let mut result: Box<And<Box<Predicate>, Box<Predicate>>> =
|
||||||
|
Box::new(And::new(subqueries.remove(0), subqueries.remove(0)));
|
||||||
|
while !subqueries.is_empty() {
|
||||||
|
result = Box::new(And::new(result, subqueries.remove(0)));
|
||||||
|
}
|
||||||
|
Ok(Box::new(result))
|
||||||
}
|
}
|
||||||
_ => Err(anyhow!(format!(
|
|
||||||
"Malformed expression: Unknown symbol {}",
|
|
||||||
symbol
|
|
||||||
))),
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
Err(anyhow!(format!(
|
QueryPart::Type(_) => unimplemented!("Type queries are not yet implemented."),
|
||||||
"Malformed expression: Inner value '{:?}' is not a symbol.",
|
},
|
||||||
value
|
Query::MultiQuery(mq) => {
|
||||||
)))
|
let subqueries: Result<Vec<Box<Predicate>>> = mq
|
||||||
|
.queries
|
||||||
|
.iter()
|
||||||
|
.map(|sq| sq.to_sqlite_predicates())
|
||||||
|
.collect();
|
||||||
|
let mut subqueries: Vec<Box<Predicate>> = subqueries?;
|
||||||
|
match subqueries.len() {
|
||||||
|
0 => Ok(Box::new(true.into_sql::<Bool>())),
|
||||||
|
1 => Ok(subqueries.remove(0)),
|
||||||
|
_ => match mq.qualifier {
|
||||||
|
QueryQualifier::AND => {
|
||||||
|
let mut result: Box<And<Box<Predicate>, Box<Predicate>>> =
|
||||||
|
Box::new(And::new(subqueries.remove(0), subqueries.remove(0)));
|
||||||
|
while !subqueries.is_empty() {
|
||||||
|
result = Box::new(And::new(result, subqueries.remove(0)));
|
||||||
|
}
|
||||||
|
Ok(Box::new(result))
|
||||||
|
}
|
||||||
|
QueryQualifier::OR => {
|
||||||
|
let mut result: Box<Or<Box<Predicate>, Box<Predicate>>> =
|
||||||
|
Box::new(Or::new(subqueries.remove(0), subqueries.remove(0)));
|
||||||
|
while !subqueries.is_empty() {
|
||||||
|
result = Box::new(Or::new(result, subqueries.remove(0)));
|
||||||
|
}
|
||||||
|
Ok(Box::new(result))
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lexpr::Value::String(str) => match T::from_str(str.borrow()) {
|
|
||||||
Ok(value) => Ok(QueryComponent::Exact(value)),
|
|
||||||
Err(error) => Err(anyhow!(format!(
|
|
||||||
"Malformed expression: Conversion of inner value '{}' from string failed: {:#?}",
|
|
||||||
str, error
|
|
||||||
))),
|
|
||||||
},
|
|
||||||
lexpr::Value::Symbol(symbol) => match symbol.borrow() {
|
|
||||||
"?" => Ok(QueryComponent::Any),
|
|
||||||
_ => Err(anyhow!(format!(
|
|
||||||
"Malformed expression: Unknown symbol {}",
|
|
||||||
symbol
|
|
||||||
))),
|
|
||||||
},
|
|
||||||
_ => Err(anyhow!(
|
|
||||||
"Malformed expression: Inner value not a string, list or '?'."
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -435,7 +539,7 @@ impl Query {
|
||||||
pub fn query<C: Connection<Backend = Sqlite>>(connection: &C, query: Query) -> Result<Vec<Entry>> {
|
pub fn query<C: Connection<Backend = Sqlite>>(connection: &C, query: Query) -> Result<Vec<Entry>> {
|
||||||
use crate::schema::data::dsl::*;
|
use crate::schema::data::dsl::*;
|
||||||
|
|
||||||
let db_query = data.filter(query_to_sqlite(&query)?);
|
let db_query = data.filter(query.to_sqlite_predicates()?);
|
||||||
|
|
||||||
trace!("Querying: {}", debug_query(&db_query));
|
trace!("Querying: {}", debug_query(&db_query));
|
||||||
|
|
||||||
|
@ -449,151 +553,6 @@ pub fn query<C: Connection<Backend = Sqlite>>(connection: &C, query: Query) -> R
|
||||||
|
|
||||||
Ok(entries)
|
Ok(entries)
|
||||||
}
|
}
|
||||||
type Predicate = dyn BoxableExpression<data::table, Sqlite, SqlType = Bool>;
|
|
||||||
|
|
||||||
fn query_to_sqlite(query: &Query) -> Result<Box<Predicate>> {
|
|
||||||
match query {
|
|
||||||
Query::SingleQuery(qp) => match qp {
|
|
||||||
QueryPart::Matches(eq) => {
|
|
||||||
let mut subqueries: Vec<Box<Predicate>> = vec![];
|
|
||||||
|
|
||||||
match &eq.entity {
|
|
||||||
QueryComponent::Exact(q_target) => {
|
|
||||||
subqueries.push(Box::new(data::target.eq(q_target.encode()?)))
|
|
||||||
}
|
|
||||||
QueryComponent::In(q_targets) => {
|
|
||||||
let targets: Result<Vec<_>, _> =
|
|
||||||
q_targets.iter().map(|t| t.encode()).collect();
|
|
||||||
subqueries.push(Box::new(data::target.eq_any(targets?)))
|
|
||||||
}
|
|
||||||
QueryComponent::Contains(_) => {
|
|
||||||
return Err(anyhow!("Addresses cannot be queried alike."))
|
|
||||||
}
|
|
||||||
QueryComponent::Any => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
match &eq.attribute {
|
|
||||||
QueryComponent::Exact(q_key) => {
|
|
||||||
subqueries.push(Box::new(data::key.eq(q_key.clone())))
|
|
||||||
}
|
|
||||||
QueryComponent::In(q_keys) => {
|
|
||||||
subqueries.push(Box::new(data::key.eq_any(q_keys.clone())))
|
|
||||||
}
|
|
||||||
QueryComponent::Contains(q_key) => {
|
|
||||||
subqueries.push(Box::new(data::key.like(format!("%{}%", q_key))))
|
|
||||||
}
|
|
||||||
QueryComponent::Any => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
match &eq.value {
|
|
||||||
QueryComponent::Exact(q_value) => {
|
|
||||||
subqueries.push(Box::new(data::value.eq(q_value.to_string()?)))
|
|
||||||
}
|
|
||||||
QueryComponent::In(q_values) => {
|
|
||||||
let values: Result<Vec<_>, _> =
|
|
||||||
q_values.iter().map(|v| v.to_string()).collect();
|
|
||||||
subqueries.push(Box::new(data::value.eq_any(values?)))
|
|
||||||
}
|
|
||||||
QueryComponent::Contains(q_value) => {
|
|
||||||
subqueries.push(Box::new(data::value.like(format!("%{}%", q_value))))
|
|
||||||
}
|
|
||||||
QueryComponent::Any => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
match subqueries.len() {
|
|
||||||
0 => Ok(Box::new(true.into_sql::<Bool>())),
|
|
||||||
1 => Ok(subqueries.remove(0)),
|
|
||||||
_ => {
|
|
||||||
let mut result: Box<And<Box<Predicate>, Box<Predicate>>> =
|
|
||||||
Box::new(And::new(subqueries.remove(0), subqueries.remove(0)));
|
|
||||||
while !subqueries.is_empty() {
|
|
||||||
result = Box::new(And::new(result, subqueries.remove(0)));
|
|
||||||
}
|
|
||||||
Ok(Box::new(result))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QueryPart::Type(_) => unimplemented!("Type queries are not yet implemented."),
|
|
||||||
},
|
|
||||||
Query::MultiQuery(mq) => {
|
|
||||||
let subqueries: Result<Vec<Box<Predicate>>> =
|
|
||||||
mq.queries.iter().map(|sq| query_to_sqlite(sq)).collect();
|
|
||||||
let mut subqueries: Vec<Box<Predicate>> = subqueries?;
|
|
||||||
match subqueries.len() {
|
|
||||||
0 => Ok(Box::new(true.into_sql::<Bool>())),
|
|
||||||
1 => Ok(subqueries.remove(0)),
|
|
||||||
_ => match mq.qualifier {
|
|
||||||
QueryQualifier::AND => {
|
|
||||||
let mut result: Box<And<Box<Predicate>, Box<Predicate>>> =
|
|
||||||
Box::new(And::new(subqueries.remove(0), subqueries.remove(0)));
|
|
||||||
while !subqueries.is_empty() {
|
|
||||||
result = Box::new(And::new(result, subqueries.remove(0)));
|
|
||||||
}
|
|
||||||
Ok(Box::new(result))
|
|
||||||
}
|
|
||||||
QueryQualifier::OR => {
|
|
||||||
let mut result: Box<Or<Box<Predicate>, Box<Predicate>>> =
|
|
||||||
Box::new(Or::new(subqueries.remove(0), subqueries.remove(0)));
|
|
||||||
while !subqueries.is_empty() {
|
|
||||||
result = Box::new(Or::new(result, subqueries.remove(0)));
|
|
||||||
}
|
|
||||||
Ok(Box::new(result))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn query_entries<C: Connection<Backend = Sqlite>>(
|
|
||||||
connection: &C,
|
|
||||||
entry_query: EntryQuery,
|
|
||||||
) -> Result<Vec<Entry>> {
|
|
||||||
use crate::schema::data::dsl::*;
|
|
||||||
|
|
||||||
let mut query = data.into_boxed();
|
|
||||||
|
|
||||||
query = match entry_query.entity {
|
|
||||||
QueryComponent::Exact(q_target) => query.filter(target.eq(q_target.encode()?)),
|
|
||||||
QueryComponent::In(q_targets) => {
|
|
||||||
let targets: Result<Vec<_>, _> = q_targets.into_iter().map(|t| t.encode()).collect();
|
|
||||||
query.filter(target.eq_any(targets?))
|
|
||||||
}
|
|
||||||
QueryComponent::Contains(_) => return Err(anyhow!("Cannot query Address alike.")),
|
|
||||||
QueryComponent::Any => query,
|
|
||||||
};
|
|
||||||
|
|
||||||
query = match entry_query.attribute {
|
|
||||||
QueryComponent::Exact(q_key) => query.filter(key.eq(q_key)),
|
|
||||||
QueryComponent::In(q_keys) => query.filter(key.eq_any(q_keys)),
|
|
||||||
QueryComponent::Contains(q_key) => query.filter(key.like(format!("%{}%", q_key))),
|
|
||||||
QueryComponent::Any => query,
|
|
||||||
};
|
|
||||||
|
|
||||||
query = match entry_query.value {
|
|
||||||
QueryComponent::Exact(q_value) => query.filter(value.eq(q_value.to_string()?)),
|
|
||||||
QueryComponent::In(q_values) => {
|
|
||||||
let values: Result<Vec<_>, _> = q_values.into_iter().map(|v| v.to_string()).collect();
|
|
||||||
query.filter(value.eq_any(values?))
|
|
||||||
}
|
|
||||||
QueryComponent::Contains(q_value_string) => {
|
|
||||||
query.filter(value.like(format!("%{}%", q_value_string)))
|
|
||||||
}
|
|
||||||
QueryComponent::Any => query,
|
|
||||||
};
|
|
||||||
|
|
||||||
trace!("Querying: {}", debug_query(&query));
|
|
||||||
|
|
||||||
let matches = query.load::<models::Entry>(connection)?;
|
|
||||||
|
|
||||||
let entries = matches
|
|
||||||
.iter()
|
|
||||||
.map(Entry::try_from)
|
|
||||||
.filter_map(Result::ok)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(entries)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_entry<C: Connection<Backend = Sqlite>>(
|
pub fn insert_entry<C: Connection<Backend = Sqlite>>(
|
||||||
connection: &C,
|
connection: &C,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::addressing::Address;
|
use crate::addressing::Address;
|
||||||
use crate::database::{
|
use crate::database::{
|
||||||
bulk_retrieve_objects, file_set_valid, insert_entry, insert_file, query_entries,
|
bulk_retrieve_objects, file_set_valid, insert_entry, insert_file, query, retrieve_all_files,
|
||||||
retrieve_all_files, DbPool, Entry, EntryQuery, EntryValue, QueryComponent, DATABASE_FILENAME,
|
DbPool, Entry, EntryQuery, EntryValue, Query, QueryComponent, QueryPart, DATABASE_FILENAME,
|
||||||
};
|
};
|
||||||
use crate::hash::Hashable;
|
use crate::hash::Hashable;
|
||||||
use crate::models;
|
use crate::models;
|
||||||
|
@ -129,22 +129,22 @@ impl EntryList for Vec<Entry> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_roots<C: Connection<Backend = Sqlite>>(connection: &C) -> Result<Vec<Entry>> {
|
pub fn list_roots<C: Connection<Backend = Sqlite>>(connection: &C) -> Result<Vec<Entry>> {
|
||||||
let all_directories: Vec<Entry> = query_entries(
|
let all_directories: Vec<Entry> = query(
|
||||||
connection,
|
connection,
|
||||||
EntryQuery {
|
Query::SingleQuery(QueryPart::Matches(EntryQuery {
|
||||||
entity: QueryComponent::Any,
|
entity: QueryComponent::Any,
|
||||||
attribute: QueryComponent::Exact(DIR_KEY.to_string()),
|
attribute: QueryComponent::Exact(DIR_KEY.to_string()),
|
||||||
value: QueryComponent::Any,
|
value: QueryComponent::Any,
|
||||||
},
|
})),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let directories_with_parents: Vec<Address> = query_entries(
|
let directories_with_parents: Vec<Address> = query(
|
||||||
connection,
|
connection,
|
||||||
EntryQuery {
|
Query::SingleQuery(QueryPart::Matches(EntryQuery {
|
||||||
entity: QueryComponent::Any,
|
entity: QueryComponent::Any,
|
||||||
attribute: QueryComponent::Exact(DIR_HAS_KEY.to_string()),
|
attribute: QueryComponent::Exact(DIR_HAS_KEY.to_string()),
|
||||||
value: QueryComponent::Any,
|
value: QueryComponent::Any,
|
||||||
},
|
})),
|
||||||
)?
|
)?
|
||||||
.extract_addresses();
|
.extract_addresses();
|
||||||
|
|
||||||
|
@ -167,13 +167,13 @@ pub async fn list_directory<C: Connection<Backend = Sqlite>>(
|
||||||
let resolved_path: Vec<Address> = resolve_path(connection, path, false)?;
|
let resolved_path: Vec<Address> = resolve_path(connection, path, false)?;
|
||||||
let last = resolved_path.last().unwrap();
|
let last = resolved_path.last().unwrap();
|
||||||
|
|
||||||
query_entries(
|
query(
|
||||||
connection,
|
connection,
|
||||||
EntryQuery {
|
Query::SingleQuery(QueryPart::Matches(EntryQuery {
|
||||||
entity: QueryComponent::Exact(last.clone()),
|
entity: QueryComponent::Exact(last.clone()),
|
||||||
attribute: QueryComponent::Exact(DIR_HAS_KEY.to_string()),
|
attribute: QueryComponent::Exact(DIR_HAS_KEY.to_string()),
|
||||||
value: QueryComponent::Any,
|
value: QueryComponent::Any,
|
||||||
},
|
})),
|
||||||
)?
|
)?
|
||||||
.extract_addresses()
|
.extract_addresses()
|
||||||
}
|
}
|
||||||
|
@ -197,13 +197,13 @@ pub fn fetch_or_create_dir<C: Connection<Backend = Sqlite>>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let dir_value = EntryValue::Value(Value::String(directory.name));
|
let dir_value = EntryValue::Value(Value::String(directory.name));
|
||||||
let directories: Vec<Address> = query_entries(
|
let directories: Vec<Address> = query(
|
||||||
connection,
|
connection,
|
||||||
EntryQuery {
|
Query::SingleQuery(QueryPart::Matches(EntryQuery {
|
||||||
entity: QueryComponent::Any,
|
entity: QueryComponent::Any,
|
||||||
attribute: QueryComponent::Exact(String::from(DIR_KEY)),
|
attribute: QueryComponent::Exact(String::from(DIR_KEY)),
|
||||||
value: QueryComponent::Exact(dir_value.clone()),
|
value: QueryComponent::Exact(dir_value.clone()),
|
||||||
},
|
})),
|
||||||
)?
|
)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|e: Entry| e.target)
|
.map(|e: Entry| e.target)
|
||||||
|
@ -211,13 +211,13 @@ pub fn fetch_or_create_dir<C: Connection<Backend = Sqlite>>(
|
||||||
|
|
||||||
let valid_directories: Vec<Address> = match parent.clone() {
|
let valid_directories: Vec<Address> = match parent.clone() {
|
||||||
Some(address) => {
|
Some(address) => {
|
||||||
let parent_has: Vec<Address> = query_entries(
|
let parent_has: Vec<Address> = query(
|
||||||
connection,
|
connection,
|
||||||
EntryQuery {
|
Query::SingleQuery(QueryPart::Matches(EntryQuery {
|
||||||
entity: QueryComponent::Exact(address),
|
entity: QueryComponent::Exact(address),
|
||||||
attribute: QueryComponent::Exact(String::from(DIR_HAS_KEY)),
|
attribute: QueryComponent::Exact(String::from(DIR_HAS_KEY)),
|
||||||
value: QueryComponent::Any,
|
value: QueryComponent::Any,
|
||||||
},
|
})),
|
||||||
)?
|
)?
|
||||||
.extract_addresses();
|
.extract_addresses();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ use futures_util::StreamExt;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -55,7 +56,7 @@ pub async fn get_query(
|
||||||
let connection = state.db_pool.get().map_err(ErrorInternalServerError)?;
|
let connection = state.db_pool.get().map_err(ErrorInternalServerError)?;
|
||||||
|
|
||||||
let sexp = lexpr::from_str(info.query.as_str()).map_err(ErrorInternalServerError)?;
|
let sexp = lexpr::from_str(info.query.as_str()).map_err(ErrorInternalServerError)?;
|
||||||
let in_query = Query::from_sexp(&sexp).map_err(ErrorInternalServerError)?;
|
let in_query = Query::try_from(&sexp).map_err(ErrorInternalServerError)?;
|
||||||
let result = query(&connection, in_query).map_err(ErrorInternalServerError)?;
|
let result = query(&connection, in_query).map_err(ErrorInternalServerError)?;
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(result))
|
Ok(HttpResponse::Ok().json(result))
|
||||||
|
|
Loading…
Reference in a new issue