diff --git a/migrations/V0047__internal_property.sql b/migrations/V0047__internal_property.sql new file mode 100644 index 0000000..7d593ee --- /dev/null +++ b/migrations/V0047__internal_property.sql @@ -0,0 +1,4 @@ +CREATE TABLE internal_property ( + property_name VARCHAR(100) PRIMARY KEY, + property_value JSONB NOT NULL +); diff --git a/migrations/schema.sql b/migrations/schema.sql index 2553432..79e3201 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -1,3 +1,8 @@ +CREATE TABLE internal_property ( + property_name VARCHAR(100) PRIMARY KEY, + property_value JSONB NOT NULL +); + CREATE TABLE background_job ( id UUID PRIMARY KEY, job_type SMALLINT NOT NULL, diff --git a/src/models/mod.rs b/src/models/mod.rs index 46196c8..bb60be7 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -9,6 +9,7 @@ pub mod notifications; pub mod oauth; pub mod posts; pub mod profiles; +pub mod properties; pub mod reactions; pub mod relationships; pub mod subscriptions; diff --git a/src/models/properties/mod.rs b/src/models/properties/mod.rs new file mode 100644 index 0000000..84c032e --- /dev/null +++ b/src/models/properties/mod.rs @@ -0,0 +1 @@ +pub mod queries; diff --git a/src/models/properties/queries.rs b/src/models/properties/queries.rs new file mode 100644 index 0000000..7adb4b3 --- /dev/null +++ b/src/models/properties/queries.rs @@ -0,0 +1,73 @@ +use serde::{ + de::DeserializeOwned, + Serialize, +}; +use serde_json::Value as JsonValue; + +use crate::database::{ + DatabaseClient, + DatabaseError, + DatabaseTypeError, +}; + +pub async fn set_internal_property( + db_client: &impl DatabaseClient, + name: &str, + value: &impl Serialize, +) -> Result<(), DatabaseError> { + let value_json = serde_json::to_value(value) + .map_err(|_| DatabaseTypeError)?; + db_client.execute( + " + INSERT INTO internal_property (property_name, property_value) + VALUES ($1, $2) + ON CONFLICT (property_name) DO UPDATE + SET property_value = $2 + ", + &[&name, &value_json], + ).await?; + Ok(()) +} + +pub async fn get_internal_property( + db_client: &impl DatabaseClient, + name: &str, +) -> Result, DatabaseError> { + let maybe_row = db_client.query_opt( + " + SELECT property_value + FROM internal_property + WHERE property_name = $1 + ", + &[&name], + ).await?; + let maybe_value = match maybe_row { + Some(row) => { + let value_json: JsonValue = row.try_get("property_value")?; + let value: T = serde_json::from_value(value_json) + .map_err(|_| DatabaseTypeError)?; + Some(value) + }, + None => None, + }; + Ok(maybe_value) +} + +#[cfg(test)] +mod tests { + use serial_test::serial; + use crate::database::test_utils::create_test_database; + use super::*; + + #[tokio::test] + #[serial] + async fn test_set_internal_property() { + let db_client = &create_test_database().await; + let name = "myproperty"; + let value = 100; + set_internal_property(db_client, name, &value).await.unwrap(); + let db_value: u32 = get_internal_property(db_client, name).await + .unwrap().unwrap_or_default(); + assert_eq!(db_value, value); + } +}