diff --git a/src/database/constants.rs b/src/database/constants.rs index 637c5e4..8baae01 100644 --- a/src/database/constants.rs +++ b/src/database/constants.rs @@ -1,28 +1,16 @@ use crate::addressing::Address; use crate::database::entry::InvariantEntry; -pub const TYPE_TYPE_VAL: &str = "TYPE"; -pub const TYPE_BASE_ATTR: &str = "TYPE"; -pub const TYPE_HAS_ATTR: &str = "TYPE_HAS"; -// pub const TYPE_ATTR_REQUIRED: &str = "TYPE_ATTR_REQUIRED"; - -pub const IS_OF_TYPE_ATTR: &str = "IS"; - -pub const HIER_TYPE_VAL: &str = "HIER"; -pub const HIER_HAS_ATTR: &str = "HAS"; +pub const IS_OF_ATTR: &str = "OF"; +pub const ATTR_BY_ATTR: &str = "BY"; pub const LABEL_ATTR: &str = "LBL"; pub const ADDED_ATTR: &str = "ADDED"; lazy_static! { - pub static ref TYPE_INVARIANT: InvariantEntry = InvariantEntry { - attribute: String::from(TYPE_BASE_ATTR), - value: TYPE_TYPE_VAL.into(), + pub static ref HIER_ROOT_INVARIANT: InvariantEntry = InvariantEntry { + attribute: String::from(IS_OF_ATTR), + value: "HIER_ROOT".into(), }; - pub static ref TYPE_ADDR: Address = TYPE_INVARIANT.entity().unwrap(); - pub static ref HIER_INVARIANT: InvariantEntry = InvariantEntry { - attribute: String::from(TYPE_BASE_ATTR), - value: HIER_TYPE_VAL.into(), - }; - pub static ref HIER_ADDR: Address = HIER_INVARIANT.entity().unwrap(); + pub static ref HIER_ROOT_ADDR: Address = HIER_ROOT_INVARIANT.entity().unwrap(); } diff --git a/src/database/hierarchies.rs b/src/database/hierarchies.rs index e9107f2..aa31f19 100644 --- a/src/database/hierarchies.rs +++ b/src/database/hierarchies.rs @@ -6,13 +6,12 @@ use lru::LruCache; use tracing::trace; use uuid::Uuid; -use crate::addressing::{Address, Addressable}; -use crate::database::constants::{ - HIER_ADDR, HIER_HAS_ATTR, HIER_INVARIANT, IS_OF_TYPE_ATTR, LABEL_ATTR, TYPE_ADDR, TYPE_HAS_ATTR, -}; -use crate::database::entry::{Entry, EntryValue}; +use crate::addressing::Address; +use crate::database::constants::LABEL_ATTR; +use crate::database::entry::Entry; use crate::database::lang::{PatternQuery, Query, QueryComponent, QueryPart}; +use super::constants::{HIER_ROOT_ADDR, HIER_ROOT_INVARIANT, IS_OF_ATTR}; use super::UpEndConnection; #[derive(Debug, Clone, Eq, PartialEq, Hash)] @@ -77,47 +76,14 @@ impl std::fmt::Display for UHierPath { } } -trait PointerEntries { - fn extract_pointers(&self) -> Vec<(Address, Address)>; -} - -impl PointerEntries for Vec { - fn extract_pointers(&self) -> Vec<(Address, Address)> { - self.iter() - .filter_map(|e| { - if let EntryValue::Address(address) = &e.value { - Some((e.address().unwrap(), address.clone())) - } else { - None - } - }) - .collect() - } -} - pub fn list_roots(connection: &UpEndConnection) -> Result> { - let all_directories: Vec = - connection.query(Query::SingleQuery(QueryPart::Matches(PatternQuery { - entity: QueryComponent::Variable(None), - attribute: QueryComponent::Exact(IS_OF_TYPE_ATTR.into()), - value: QueryComponent::Exact(HIER_ADDR.clone().into()), - })))?; - - // TODO: this is horrible - let directories_with_parents: Vec
= connection + Ok(connection .query(Query::SingleQuery(QueryPart::Matches(PatternQuery { entity: QueryComponent::Variable(None), - attribute: QueryComponent::Exact(HIER_HAS_ATTR.into()), - value: QueryComponent::Variable(None), + attribute: QueryComponent::Exact(IS_OF_ATTR.into()), + value: QueryComponent::Exact((*HIER_ROOT_ADDR).clone().into()), })))? - .extract_pointers() .into_iter() - .map(|(_, val)| val) - .collect(); - - Ok(all_directories - .into_iter() - .filter(|entry| !directories_with_parents.contains(&entry.entity)) .map(|e| e.entity) .collect()) } @@ -154,13 +120,12 @@ pub fn fetch_or_create_dir( let parent_has: Vec
= match parent.clone() { Some(parent) => connection .query(Query::SingleQuery(QueryPart::Matches(PatternQuery { - entity: QueryComponent::Exact(parent), - attribute: QueryComponent::Exact(HIER_HAS_ATTR.into()), - value: QueryComponent::Variable(None), + entity: QueryComponent::Variable(None), + attribute: QueryComponent::Exact(IS_OF_ATTR.into()), + value: QueryComponent::Exact(parent.into()), })))? - .extract_pointers() .into_iter() - .map(|(_, val)| val) + .map(|e| e.entity) .collect(), None => list_roots(connection)?, }; @@ -173,14 +138,6 @@ pub fn fetch_or_create_dir( 0 => { if create { let new_directory_address = Address::Uuid(Uuid::new_v4()); - let type_entry = Entry { - entity: new_directory_address.clone(), - attribute: String::from(IS_OF_TYPE_ATTR), - value: HIER_ADDR.clone().into(), - provenance: "SYSTEM FS".to_string(), - timestamp: chrono::Utc::now().naive_utc(), - }; - connection.insert_entry(type_entry)?; let directory_entry = Entry { entity: new_directory_address.clone(), @@ -191,16 +148,23 @@ pub fn fetch_or_create_dir( }; connection.insert_entry(directory_entry)?; - if let Some(parent) = parent { - let has_entry = Entry { - entity: parent, - attribute: String::from(HIER_HAS_ATTR), - value: new_directory_address.clone().into(), + connection.insert_entry(if let Some(parent) = parent { + Entry { + entity: new_directory_address.clone(), + attribute: String::from(IS_OF_ATTR), + value: parent.into(), provenance: "SYSTEM FS".to_string(), timestamp: chrono::Utc::now().naive_utc(), - }; - connection.insert_entry(has_entry)?; - } + } + } else { + Entry { + entity: new_directory_address.clone(), + attribute: String::from(IS_OF_ATTR), + value: HIER_ROOT_ADDR.clone().into(), + provenance: "SYSTEM FS".to_string(), + timestamp: chrono::Utc::now().naive_utc(), + } + })?; Ok(new_directory_address) } else { @@ -269,10 +233,8 @@ pub fn resolve_path_cached( } pub fn initialize_hier(connection: &UpEndConnection) -> Result<()> { - connection.insert_entry(Entry::try_from(&*HIER_INVARIANT)?)?; - upend_insert_addr!(connection, HIER_ADDR, IS_OF_TYPE_ATTR, TYPE_ADDR)?; - upend_insert_val!(connection, HIER_ADDR, TYPE_HAS_ATTR, HIER_HAS_ATTR)?; - upend_insert_val!(connection, HIER_ADDR, LABEL_ATTR, "Group")?; + connection.insert_entry(Entry::try_from(&*HIER_ROOT_INVARIANT)?)?; + upend_insert_val!(connection, HIER_ROOT_ADDR, LABEL_ATTR, "Hierarchy Root")?; Ok(()) } diff --git a/src/database/mod.rs b/src/database/mod.rs index 2e39685..dc3054f 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -14,9 +14,6 @@ pub mod lang; use crate::addressing::{Address, Addressable}; use crate::common::build; -use crate::database::constants::{ - IS_OF_TYPE_ATTR, LABEL_ATTR, TYPE_ADDR, TYPE_HAS_ATTR, TYPE_INVARIANT, TYPE_TYPE_VAL, -}; use crate::database::engine::execute; use crate::database::entry::{Entry, EntryValue, ImmutableEntry}; use crate::database::inner::models; @@ -161,13 +158,6 @@ impl UpEndDatabase { }, )?; - trace!("Initializing types..."); - connection.insert_entry(Entry::try_from(&*TYPE_INVARIANT)?)?; - upend_insert_addr!(connection, TYPE_ADDR, IS_OF_TYPE_ATTR, TYPE_ADDR)?; - upend_insert_val!(connection, TYPE_ADDR, TYPE_HAS_ATTR, TYPE_HAS_ATTR)?; - upend_insert_val!(connection, TYPE_ADDR, TYPE_HAS_ATTR, TYPE_TYPE_VAL)?; - upend_insert_val!(connection, TYPE_ADDR, LABEL_ATTR, "UpEnd Type")?; - initialize_hier(&connection)?; Ok(OpenResult { db, new }) @@ -378,6 +368,8 @@ impl UpEndConnection { #[cfg(test)] mod test { + use crate::database::constants::LABEL_ATTR; + use super::*; use tempfile::TempDir; diff --git a/src/database/stores/fs/mod.rs b/src/database/stores/fs/mod.rs index 276c807..456fb32 100644 --- a/src/database/stores/fs/mod.rs +++ b/src/database/stores/fs/mod.rs @@ -2,11 +2,8 @@ use self::db::files; use super::{Blob, StoreError, UpStore, UpdatePathOutcome}; use crate::addressing::Address; -use crate::database::constants::{ - ADDED_ATTR, HIER_HAS_ATTR, IS_OF_TYPE_ATTR, LABEL_ATTR, TYPE_ADDR, TYPE_BASE_ATTR, - TYPE_HAS_ATTR, -}; -use crate::database::entry::{Entry, InvariantEntry}; +use crate::database::constants::{ADDED_ATTR, ATTR_BY_ATTR, IS_OF_ATTR, LABEL_ATTR}; +use crate::database::entry::Entry; use crate::database::hierarchies::{ resolve_path, resolve_path_cached, ResolveCache, UHierPath, UNode, }; @@ -24,7 +21,7 @@ use lru::LruCache; use rayon::prelude::*; use serde_json::json; use std::borrow::Borrow; -use std::convert::{TryFrom, TryInto}; +use std::convert::TryInto; use std::path::PathBuf; use std::path::{Component, Path}; use std::sync::{Arc, Mutex, RwLock}; @@ -35,19 +32,9 @@ use walkdir::WalkDir; mod db; -const BLOB_TYPE: &str = "BLOB"; -const ALIAS_KEY: &str = "ALIAS"; pub const FILE_MIME_KEY: &str = "FILE_MIME"; const FILE_SIZE_KEY: &str = "FILE_SIZE"; -lazy_static! { - static ref BLOB_TYPE_INVARIANT: InvariantEntry = InvariantEntry { - attribute: String::from(TYPE_BASE_ATTR), - value: BLOB_TYPE.into(), - }; - static ref BLOB_TYPE_ADDR: Address = BLOB_TYPE_INVARIANT.entity().unwrap(); -} - pub struct FsStore { path: PathBuf, pool: r2d2::Pool>, @@ -116,14 +103,6 @@ impl FsStore { let db = db.borrow(); let upconnection = db.connection()?; - // Initialize types, etc... - debug!("Initializing DB types."); - upconnection.insert_entry(Entry::try_from(&*BLOB_TYPE_INVARIANT)?)?; - upend_insert_addr!(upconnection, BLOB_TYPE_ADDR, IS_OF_TYPE_ATTR, TYPE_ADDR)?; - upend_insert_val!(upconnection, BLOB_TYPE_ADDR, TYPE_HAS_ATTR, FILE_SIZE_KEY)?; - upend_insert_val!(upconnection, BLOB_TYPE_ADDR, TYPE_HAS_ATTR, FILE_MIME_KEY)?; - upend_insert_val!(upconnection, BLOB_TYPE_ADDR, LABEL_ATTR, "Data Blob")?; - // Walk through the vault, find all paths debug!("Traversing vault directory"); let absolute_dir_path = fs::canonicalize(&*self.path)?; @@ -411,14 +390,6 @@ impl FsStore { let blob_address = Address::Hash(hash); // Metadata - let type_entry = Entry { - entity: blob_address.clone(), - attribute: String::from(IS_OF_TYPE_ATTR), - value: BLOB_TYPE_ADDR.clone().into(), - provenance: "SYSTEM INIT".to_string(), - timestamp: chrono::Utc::now().naive_utc(), - }; - let size_entry = Entry { entity: blob_address.clone(), attribute: FILE_SIZE_KEY.to_string(), @@ -467,7 +438,6 @@ impl FsStore { // Insert all let file_count = self.insert_file(new_file)?; - connection.insert_entry_immutable(type_entry)?; connection.insert_entry_immutable(size_entry)?; if file_count == 1 { connection.insert_entry_immutable(added_entry)?; @@ -477,9 +447,9 @@ impl FsStore { } let dir_has_entry = Entry { - entity: parent_dir.clone(), - attribute: HIER_HAS_ATTR.to_string(), - value: blob_address.clone().into(), + entity: blob_address.clone(), + attribute: IS_OF_ATTR.to_string(), + value: parent_dir.clone().into(), provenance: "SYSTEM INIT".to_string(), timestamp: chrono::Utc::now().naive_utc(), }; @@ -498,7 +468,7 @@ impl FsStore { let alias_entry = Entry { entity: dir_has_entry_addr, - attribute: ALIAS_KEY.to_string(), + attribute: ATTR_BY_ATTR.to_string(), value: label_entry_addr.into(), provenance: "SYSTEM INIT".to_string(), timestamp: chrono::Utc::now().naive_utc(), diff --git a/webui/src/components/Inspect.svelte b/webui/src/components/Inspect.svelte index 047ff43..5ca3e54 100644 --- a/webui/src/components/Inspect.svelte +++ b/webui/src/components/Inspect.svelte @@ -45,7 +45,9 @@ $: ({ entity, entityInfo, error, revalidate } = useEntity(address)); - $: allTypeAddresses = ($entity?.attr["IS"] || []).map((attr) => attr.value.c); + $: allTypeAddresses = ($entity?.attr["OF"] || []) + .filter((attr) => attr.value.t == "Address") + .map((attr) => attr.value.c); $: allTypeEntries = query( `(matches (in ${allTypeAddresses.map((addr) => `@${addr}`).join(" ")}) ? ?)`