diff --git a/migrations/upend/00_initial_structure/up.sql b/migrations/upend/00_initial_structure/up.sql index 75f8ad4..02bd70d 100644 --- a/migrations/upend/00_initial_structure/up.sql +++ b/migrations/upend/00_initial_structure/up.sql @@ -29,6 +29,7 @@ CREATE TABLE data entity BLOB NOT NULL, attribute VARCHAR NOT NULL, value VARCHAR NOT NULL, + immutable BOOLEAN NOT NULL, UNIQUE (entity, attribute, value) ); diff --git a/src/database/entry.rs b/src/database/entry.rs index eb1d239..ce7c3fb 100644 --- a/src/database/entry.rs +++ b/src/database/entry.rs @@ -20,6 +20,9 @@ pub struct Entry { pub value: EntryValue, } +#[derive(Debug, Clone)] +pub struct ImmutableEntry(pub Entry); + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct InvariantEntry { pub attribute: String, @@ -55,6 +58,21 @@ impl TryFrom<&Entry> for models::Entry { entity: e.entity.encode()?, attribute: e.attribute.clone(), value: e.value.to_string()?, + immutable: false, + }) + } +} + +impl TryFrom<&ImmutableEntry> for models::Entry { + type Error = anyhow::Error; + + fn try_from(e: &ImmutableEntry) -> Result { + Ok(models::Entry { + identity: e.0.address()?.encode()?, + entity: e.0.entity.encode()?, + attribute: e.0.attribute.clone(), + value: e.0.value.to_string()?, + immutable: true, }) } } diff --git a/src/database/inner/models.rs b/src/database/inner/models.rs index 7524ce7..832d791 100644 --- a/src/database/inner/models.rs +++ b/src/database/inner/models.rs @@ -46,4 +46,5 @@ pub struct Entry { pub entity: Vec, pub attribute: String, pub value: String, + pub immutable: bool, } diff --git a/src/database/inner/schema.rs b/src/database/inner/schema.rs index c41bbf5..65c2de0 100644 --- a/src/database/inner/schema.rs +++ b/src/database/inner/schema.rs @@ -4,6 +4,7 @@ table! { entity -> Binary, attribute -> Text, value -> Text, + immutable -> Bool, } } diff --git a/src/database/mod.rs b/src/database/mod.rs index 75ac0cc..cfa3ab6 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -11,11 +11,11 @@ pub mod lang; use crate::addressing::{Address, Addressable}; use crate::database::constants::{IS_OF_TYPE_ATTR, TYPE_ADDR, TYPE_HAS_ATTR, TYPE_INVARIANT}; -use crate::database::entry::{Entry, EntryValue}; +use crate::database::entry::{Entry, EntryValue, ImmutableEntry}; use crate::database::inner::models; use crate::database::inner::schema::data; use crate::database::lang::Query; -use crate::util::hash::{Hash, Hashable}; +use crate::util::hash::Hash; use crate::util::LoggerSink; use anyhow::{anyhow, Result}; use chrono::NaiveDateTime; @@ -336,13 +336,19 @@ impl UpEndConnection { pub fn insert_entry(&self, entry: Entry) -> Result
{ debug!("Inserting: {}", entry); + let entry = models::Entry::try_from(&entry)?; + self._insert_entry(entry) + } - let insert_entry = models::Entry::try_from(&entry)?; - - let entry = Entry::try_from(&insert_entry)?; + pub fn insert_entry_immutable(&self, entry: Entry) -> Result
{ + debug!("Inserting immutably: {}", entry); + let entry = models::Entry::try_from(&ImmutableEntry(entry))?; + self._insert_entry(entry) + } + fn _insert_entry(&self, entry: models::Entry) -> Result
{ let result = diesel::insert_into(data::table) - .values(insert_entry) + .values(&entry) .execute(&self.conn); if let Some(error) = result.err() { @@ -352,7 +358,7 @@ impl UpEndConnection { } } - Ok(Address::Hash(entry.hash()?)) + Ok(Address::Hash(Hash(entry.identity))) } // #[deprecated] diff --git a/src/filesystem.rs b/src/filesystem.rs index d052e7c..b31cab6 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -363,8 +363,8 @@ fn _process_directory_entry>( connection.transaction::<_, Error, _>(|| { connection.insert_file(new_file)?; - connection.insert_entry(type_entry)?; - connection.insert_entry(size_entry)?; + connection.insert_entry_immutable(type_entry)?; + connection.insert_entry_immutable(size_entry)?; if let Some(mime_entry) = mime_entry { connection.insert_entry(mime_entry)?; }