use super::PublicationVersion;
use crate::db::DatabaseTransaction;
use async_trait::async_trait;
use std::collections::HashSet;
#[async_trait]
impl super::TxManager for DatabaseTransaction {
async fn create(
&mut self,
hash_id: &str,
publication_id: &str,
codified_date: &str,
) -> anyhow::Result<Option<i64>> {
let statement = "
INSERT OR IGNORE INTO publication_version ( id, publication_id, version )
VALUES ( $1, $2, $3 )
";
let id = sqlx::query(statement)
.bind(hash_id)
.bind(publication_id)
.bind(codified_date)
.execute(&mut *self.tx)
.await?
.last_insert_id();
Ok(id)
}
async fn find_last_inserted_date_by_publication_id(
&mut self,
publication_id: &str,
) -> anyhow::Result<Option<PublicationVersion>> {
let statement = "
SELECT *
FROM publication_version
WHERE publication_id = $1
ORDER BY version DESC
LIMIT 1
";
let row = sqlx::query_as::<_, PublicationVersion>(statement)
.bind(publication_id)
.fetch_one(&mut *self.tx)
.await
.ok();
Ok(row)
}
async fn find_all_by_publication_id(
&mut self,
publication_id: &str,
) -> anyhow::Result<Vec<PublicationVersion>> {
let statement = "
SELECT *
FROM publication_version
WHERE publication_id = $1
";
let rows = sqlx::query_as::<_, PublicationVersion>(statement)
.bind(publication_id)
.fetch_all(&mut *self.tx)
.await?;
Ok(rows)
}
async fn find_all_in_publication_has_publication_versions(
&mut self,
publication_ids: Vec<String>,
) -> anyhow::Result<Vec<PublicationVersion>> {
let parameters = publication_ids
.iter()
.map(|_| "?")
.collect::<Vec<&str>>()
.join(", ");
let statement = format!(
"
SELECT DISTINCT *
FROM publication_has_publication_versions phpv
JOIN publication_version pv ON pv.id = phpv.publication_version_id
WHERE phpv.publication_id IN ({parameters})
"
);
let mut query = sqlx::query_as::<_, PublicationVersion>(&statement);
for id in publication_ids {
query = query.bind(id);
}
let rows = query.fetch_all(&mut *self.tx).await?;
Ok(rows)
}
async fn find_by_publication_id_and_version(
&mut self,
publication_id: &str,
version: &str,
) -> anyhow::Result<Option<PublicationVersion>> {
let statement = "
SELECT *
FROM publication_version
WHERE publication_id = $1 AND version = $2
";
let row = sqlx::query_as::<_, PublicationVersion>(statement)
.bind(publication_id)
.bind(version)
.fetch_one(&mut *self.tx)
.await
.ok();
Ok(row)
}
async fn find_all_recursive_for_publication(
&mut self,
publication_id: String,
) -> anyhow::Result<Vec<PublicationVersion>> {
let mut versions: HashSet<PublicationVersion> = self
.find_all_by_publication_id(&publication_id)
.await?
.into_iter()
.collect();
let mut checked_publication_ids = HashSet::new();
checked_publication_ids.insert(publication_id.clone());
let mut publication_ids_to_check = HashSet::new();
publication_ids_to_check.insert(publication_id);
while !publication_ids_to_check.is_empty() {
let new_versions: HashSet<PublicationVersion> = self
.find_all_in_publication_has_publication_versions(
publication_ids_to_check.clone().into_iter().collect(),
)
.await?
.into_iter()
.collect();
versions.extend(new_versions.clone());
checked_publication_ids.extend(publication_ids_to_check.clone());
publication_ids_to_check = new_versions
.clone()
.into_iter()
.filter(|pv| !checked_publication_ids.contains(&pv.publication_id.clone()))
.map(|pv| pv.publication_id)
.collect();
}
Ok(versions.into_iter().collect())
}
}