introduce the concept of a hierarchy root

feat/vaults
Tomáš Mládek 2021-08-18 11:06:39 +02:00
parent 2944ce3d81
commit 96d0ec3be7
1 changed files with 68 additions and 75 deletions

View File

@ -12,10 +12,18 @@ use crate::database::constants::{
HIER_ADDR, HIER_HAS_ATTR, HIER_INVARIANT, HIER_LABEL_ATTR, IS_OF_TYPE_ATTR, TYPE_ADDR, HIER_ADDR, HIER_HAS_ATTR, HIER_INVARIANT, HIER_LABEL_ATTR, IS_OF_TYPE_ATTR, TYPE_ADDR,
TYPE_HAS_ATTR, TYPE_ID_ATTR, TYPE_HAS_ATTR, TYPE_ID_ATTR,
}; };
use crate::database::entry::{Entry, EntryValue}; use crate::database::entry::{Entry, EntryValue, InvariantEntry};
use crate::database::lang::{EntryQuery, Query, QueryComponent, QueryPart}; use crate::database::lang::{EntryQuery, Query, QueryComponent, QueryPart};
use crate::database::{bulk_retrieve_objects, insert_entry, query, DbPool}; use crate::database::{bulk_retrieve_objects, insert_entry, query, DbPool};
lazy_static! {
static ref HIER_ROOT_INVARIANT: InvariantEntry = InvariantEntry {
attribute: String::from(HIER_LABEL_ATTR),
value: EntryValue::Value(Value::from("/")),
};
static ref HIER_ROOT_INVARIANT_ADDR: Address = HIER_ROOT_INVARIANT.entity().unwrap();
}
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct UNode(String); pub struct UNode(String);
@ -94,53 +102,49 @@ impl EntryList for Vec<Entry> {
} }
} }
pub fn list_roots<C: Connection<Backend = Sqlite>>(connection: &C) -> Result<Vec<Address>> { // pub fn list_orphans<C: Connection<Backend = Sqlite>>(connection: &C) -> Result<Vec<Address>> {
let all_directories: Vec<Entry> = query( // let all_directories: Vec<Entry> = query(
connection, // connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery { // Query::SingleQuery(QueryPart::Matches(EntryQuery {
entity: QueryComponent::Any, // entity: QueryComponent::Any,
attribute: QueryComponent::Exact(IS_OF_TYPE_ATTR.to_string()), // attribute: QueryComponent::Exact(IS_OF_TYPE_ATTR.to_string()),
value: QueryComponent::Exact(EntryValue::Address(HIER_ADDR.clone())), // value: QueryComponent::Exact(EntryValue::Address(HIER_ADDR.clone())),
})), // })),
)?; // )?;
//
let directories_with_parents: Vec<Address> = query( // let directories_with_parents: Vec<Address> = query(
connection, // connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery { // Query::SingleQuery(QueryPart::Matches(EntryQuery {
entity: QueryComponent::Any, // entity: QueryComponent::Any,
attribute: QueryComponent::Exact(HIER_HAS_ATTR.to_string()), // attribute: QueryComponent::Exact(HIER_HAS_ATTR.to_string()),
value: QueryComponent::Any, // value: QueryComponent::Any,
})), // })),
)? // )?
.extract_addresses(); // .extract_addresses();
//
Ok(all_directories // Ok(all_directories
.into_iter() // .into_iter()
.filter(|entry| !directories_with_parents.contains(&entry.entity)) // .filter(|entry| !directories_with_parents.contains(&entry.entity))
.map(|e| e.entity) // .map(|e| e.entity)
.collect()) // .collect())
} // }
pub async fn list_node<C: Connection<Backend = Sqlite>>( pub async fn list_node<C: Connection<Backend = Sqlite>>(
connection: &C, connection: &C,
path: &UPath, path: &UPath,
) -> Result<Vec<Entry>> { ) -> Result<Vec<Entry>> {
let entry_addresses = if path.0.is_empty() { let resolved_path: Vec<Address> = resolve_path(connection, path, false)?;
list_roots(connection)? let last = resolved_path.last().unwrap();
} else {
let resolved_path: Vec<Address> = resolve_path(connection, path, false)?;
let last = resolved_path.last().unwrap();
query( let entry_addresses = query(
connection, connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery { Query::SingleQuery(QueryPart::Matches(EntryQuery {
entity: QueryComponent::Exact(last.clone()), entity: QueryComponent::Exact(last.clone()),
attribute: QueryComponent::Exact(HIER_HAS_ATTR.to_string()), attribute: QueryComponent::Exact(HIER_HAS_ATTR.to_string()),
value: QueryComponent::Any, value: QueryComponent::Any,
})), })),
)? )?
.extract_addresses() .extract_addresses();
};
Ok(bulk_retrieve_objects(connection, entry_addresses)? Ok(bulk_retrieve_objects(connection, entry_addresses)?
.into_iter() .into_iter()
@ -159,6 +163,8 @@ pub fn fetch_or_create_dir<C: Connection<Backend = Sqlite>>(
None => trace!("FETCHING/CREATING /{:#}", directory), None => trace!("FETCHING/CREATING /{:#}", directory),
} }
let parent = parent.unwrap_or_else(|| HIER_ROOT_INVARIANT_ADDR.clone());
let matching_directories: Vec<Address> = query( let matching_directories: Vec<Address> = query(
connection, connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery { Query::SingleQuery(QueryPart::Matches(EntryQuery {
@ -173,31 +179,20 @@ pub fn fetch_or_create_dir<C: Connection<Backend = Sqlite>>(
.map(|e: Entry| e.entity) .map(|e: Entry| e.entity)
.collect(); .collect();
let valid_directories: Vec<Address> = match parent.clone() { let parent_has: Vec<Address> = query(
Some(address) => { connection,
let parent_has: Vec<Address> = query( Query::SingleQuery(QueryPart::Matches(EntryQuery {
connection, entity: QueryComponent::Exact(parent.clone()),
Query::SingleQuery(QueryPart::Matches(EntryQuery { attribute: QueryComponent::Exact(String::from(HIER_HAS_ATTR)),
entity: QueryComponent::Exact(address), value: QueryComponent::Any,
attribute: QueryComponent::Exact(String::from(HIER_HAS_ATTR)), })),
value: QueryComponent::Any, )?
})), .extract_addresses();
)?
.extract_addresses();
matching_directories let valid_directories: Vec<Address> = matching_directories
.into_iter() .into_iter()
.filter(|a| parent_has.contains(a)) .filter(|a| parent_has.contains(a))
.collect() .collect();
}
None => {
let roots = list_roots(connection)?;
matching_directories
.into_iter()
.filter(|a| roots.contains(a))
.collect()
}
};
match valid_directories.len() { match valid_directories.len() {
0 => { 0 => {
@ -217,14 +212,12 @@ pub fn fetch_or_create_dir<C: Connection<Backend = Sqlite>>(
}; };
insert_entry(connection, directory_entry)?; insert_entry(connection, directory_entry)?;
if let Some(parent_addr) = parent { let has_entry = Entry {
let has_entry = Entry { entity: parent,
entity: parent_addr, attribute: String::from(HIER_HAS_ATTR),
attribute: String::from(HIER_HAS_ATTR), value: EntryValue::Address(new_directory_address.clone()),
value: EntryValue::Address(new_directory_address.clone()), };
}; insert_entry(connection, has_entry)?;
insert_entry(connection, has_entry)?;
}
Ok(new_directory_address) Ok(new_directory_address)
} else { } else {
@ -243,7 +236,7 @@ pub fn resolve_path<C: Connection<Backend = Sqlite>>(
path: &UPath, path: &UPath,
create: bool, create: bool,
) -> Result<Vec<Address>> { ) -> Result<Vec<Address>> {
let mut result: Vec<Address> = vec![]; let mut result: Vec<Address> = vec![HIER_ROOT_INVARIANT_ADDR.clone()];
let mut path_stack = path.0.to_vec(); let mut path_stack = path.0.to_vec();
path_stack.reverse(); path_stack.reverse();