summaryrefslogtreecommitdiffstats
path: root/rust/src/entity_crud.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/entity_crud.rs')
-rw-r--r--rust/src/entity_crud.rs175
1 files changed, 128 insertions, 47 deletions
diff --git a/rust/src/entity_crud.rs b/rust/src/entity_crud.rs
index ce1c1ed7..a92c45a6 100644
--- a/rust/src/entity_crud.rs
+++ b/rust/src/entity_crud.rs
@@ -8,7 +8,7 @@
use crate::database_models::*;
use crate::database_schema::*;
use crate::editing::EditContext;
-use crate::endpoint_handlers::get_release_files;
+use crate::endpoint_handlers::{get_release_files, get_release_filesets, get_release_webcaptures};
use crate::errors::*;
use crate::identifiers::*;
use crate::server::DbConn;
@@ -798,8 +798,7 @@ impl EntityCrud for ContainerEntity {
wikidata_qid: None,
publisher: None,
name: None,
- abbrev: None,
- coden: None,
+ container_type: None,
state: Some(ident_row.state().unwrap().shortname()),
ident: Some(FatcatId::from_uuid(&ident_row.id).to_string()),
revision: ident_row.rev_id.map(|u| u.to_string()),
@@ -831,8 +830,7 @@ impl EntityCrud for ContainerEntity {
wikidata_qid: rev_row.wikidata_qid,
publisher: rev_row.publisher,
name: Some(rev_row.name),
- abbrev: rev_row.abbrev,
- coden: rev_row.coden,
+ container_type: rev_row.container_type,
state,
ident: ident_id,
revision: Some(rev_row.id.to_string()),
@@ -869,8 +867,7 @@ impl EntityCrud for ContainerEntity {
publisher: model.publisher.clone(),
issnl: model.issnl.clone(),
wikidata_qid: model.wikidata_qid.clone(),
- abbrev: model.abbrev.clone(),
- coden: model.coden.clone(),
+ container_type: model.container_type.clone(),
extra_json: model.extra.clone(),
})
.collect::<Vec<ContainerRevNewRow>>(),
@@ -1619,6 +1616,7 @@ impl EntityCrud for ReleaseEntity {
Ok(ReleaseEntity {
title: None,
+ original_title: None,
release_type: None,
release_status: None,
release_date: None,
@@ -1627,8 +1625,10 @@ impl EntityCrud for ReleaseEntity {
pmid: None,
pmcid: None,
isbn13: None,
- core_id: None,
wikidata_qid: None,
+ core_id: None,
+ arxiv_id: None,
+ jstor_id: None,
volume: None,
issue: None,
pages: None,
@@ -1639,6 +1639,7 @@ impl EntityCrud for ReleaseEntity {
container_id: None,
publisher: None,
language: None,
+ license_slug: None,
work_id: None,
refs: None,
contribs: None,
@@ -1675,6 +1676,26 @@ impl EntityCrud for ReleaseEntity {
};
self.files = Some(get_release_files(conn, ident, HideFlags::none())?);
}
+ if expand.filesets && self.ident.is_some() {
+ let ident = match &self.ident {
+ None => bail!("Can't expand filesets on a non-concrete entity"), // redundant with above is_some()
+ Some(ident) => match &self.redirect {
+ None => FatcatId::from_str(&ident)?,
+ Some(redir) => FatcatId::from_str(&redir)?,
+ },
+ };
+ self.filesets = Some(get_release_filesets(conn, ident, HideFlags::none())?);
+ }
+ if expand.webcaptures && self.ident.is_some() {
+ let ident = match &self.ident {
+ None => bail!("Can't expand webcaptures on a non-concrete entity"), // redundant with above is_some()
+ Some(ident) => match &self.redirect {
+ None => FatcatId::from_str(&ident)?,
+ Some(redir) => FatcatId::from_str(&redir)?,
+ },
+ };
+ self.webcaptures = Some(get_release_webcaptures(conn, ident, HideFlags::none())?);
+ }
if expand.container {
if let Some(ref cid) = self.container_id {
self.container = Some(ContainerEntity::db_get(
@@ -1812,28 +1833,28 @@ impl EntityCrud for ReleaseEntity {
None => (None, None, None),
};
- let refs: Option<Vec<ReleaseRef>> = match hide.refs {
- true => None,
- false => Some(
- release_ref::table
+ let refs: Option<Vec<ReleaseRef>> = match (hide.refs, rev_row.refs_blob_sha1) {
+ (true, _) => None,
+ (false, None) => Some(vec![]),
+ (false, Some(sha1)) => Some({
+ let refs_blob: RefsBlobRow = refs_blob::table
+ .find(sha1) // checked in match
+ .get_result(conn)?;
+ let refs: Vec<RefsBlobJson> = serde_json::from_value(refs_blob.refs_json)?;
+ let mut refs: Vec<ReleaseRef> = refs.into_iter().map(|j| j.into_model()).collect();
+ let ref_rows: Vec<ReleaseRefRow> = release_ref::table
.filter(release_ref::release_rev.eq(rev_row.id))
.order(release_ref::index_val.asc())
- .get_results(conn)?
- .into_iter()
- .map(|r: ReleaseRefRow| ReleaseRef {
- index: r.index_val.map(|v| v as i64),
- key: r.key,
- extra: r.extra_json,
- container_name: r.container_name,
- year: r.year.map(|v| v as i64),
- title: r.title,
- locator: r.locator,
- target_release_id: r
- .target_release_ident_id
- .map(|v| FatcatId::from_uuid(&v).to_string()),
- })
- .collect(),
- ),
+ .get_results(conn)?;
+ for index in 0..refs.len() {
+ refs[index].index = Some(index as i64)
+ }
+ for row in ref_rows {
+ refs[row.index_val as usize].target_release_id =
+ Some(FatcatId::from_uuid(&row.target_release_ident_id).to_string());
+ }
+ refs
+ }),
};
let contribs: Option<Vec<ReleaseContrib>> = match hide.contribs {
@@ -1851,6 +1872,7 @@ impl EntityCrud for ReleaseEntity {
index: c.index_val.map(|v| v as i64),
raw_name: c.raw_name,
role: c.role,
+ raw_affiliation: c.raw_affiliation,
extra: c.extra_json,
creator_id: c
.creator_ident_id
@@ -1884,6 +1906,7 @@ impl EntityCrud for ReleaseEntity {
Ok(ReleaseEntity {
title: Some(rev_row.title),
+ original_title: rev_row.original_title,
release_type: rev_row.release_type,
release_status: rev_row.release_status,
release_date: rev_row.release_date,
@@ -1892,8 +1915,10 @@ impl EntityCrud for ReleaseEntity {
pmid: rev_row.pmid,
pmcid: rev_row.pmcid,
isbn13: rev_row.isbn13,
- core_id: rev_row.core_id,
wikidata_qid: rev_row.wikidata_qid,
+ core_id: rev_row.core_id,
+ arxiv_id: rev_row.arxiv_id,
+ jstor_id: rev_row.jstor_id,
volume: rev_row.volume,
issue: rev_row.issue,
pages: rev_row.pages,
@@ -1906,6 +1931,7 @@ impl EntityCrud for ReleaseEntity {
.map(|u| FatcatId::from_uuid(&u).to_string()),
publisher: rev_row.publisher,
language: rev_row.language,
+ license_slug: rev_row.license_slug,
work_id: Some(FatcatId::from_uuid(&rev_row.work_ident_id).to_string()),
refs,
contribs,
@@ -1934,6 +1960,7 @@ impl EntityCrud for ReleaseEntity {
if let Some(ref extid) = entity.wikidata_qid {
check_wikidata_qid(extid)?;
}
+ // TODO: JSTOR and arxiv IDs
if let Some(ref release_type) = entity.release_type {
check_release_type(release_type)?;
}
@@ -1953,13 +1980,65 @@ impl EntityCrud for ReleaseEntity {
.into());
}
+ // First, calculate and upsert any refs JSON blobs and record the SHA1 keys, so they can be
+ // included in the release_rev row itself
+ let mut refs_blob_rows: Vec<RefsBlobRow> = vec![];
+ let mut refs_blob_sha1: Vec<Option<String>> = vec![];
+ for model in models.iter() {
+ match &model.refs {
+ None => {
+ refs_blob_sha1.push(None);
+ }
+ Some(ref_list) => {
+ if ref_list.is_empty() {
+ refs_blob_sha1.push(None);
+ continue;
+ }
+ // Have to strip out target refs and indexes, or hashing won't work well when
+ // these change
+ let ref_list: Vec<RefsBlobJson> = ref_list
+ .iter()
+ .map(|r: &ReleaseRef| {
+ let mut r = RefsBlobJson::from_model(r);
+ r.target_release_id = None;
+ r.index = None;
+ r
+ })
+ .collect();
+ // TODO: maybe `canonical_json` crate?
+ let refs_json = serde_json::to_value(ref_list)?;
+ let refs_str = refs_json.to_string();
+ let sha1 = Sha1::from(refs_str).hexdigest();
+ let blob = RefsBlobRow {
+ sha1: sha1.clone(),
+ refs_json,
+ };
+ refs_blob_rows.push(blob);
+ refs_blob_sha1.push(Some(sha1));
+ }
+ };
+ }
+
+ if !refs_blob_rows.is_empty() {
+ // Sort of an "upsert"; only inserts new abstract rows if they don't already exist
+ insert_into(refs_blob::table)
+ .values(&refs_blob_rows)
+ .on_conflict(refs_blob::sha1)
+ .do_nothing()
+ .execute(conn)?;
+ }
+
+ // Then the main release_revs themselves
let rev_ids: Vec<Uuid> = insert_into(release_rev::table)
.values(
models
.iter()
- .map(|model| {
+ .zip(refs_blob_sha1.into_iter())
+ .map(|(model, refs_sha1)| {
Ok(ReleaseRevNewRow {
+ refs_blob_sha1: refs_sha1,
title: model.title.clone().unwrap(), // titles checked above
+ original_title: model.original_title.clone(),
release_type: model.release_type.clone(),
release_status: model.release_status.clone(),
release_date: model.release_date,
@@ -1970,6 +2049,8 @@ impl EntityCrud for ReleaseEntity {
wikidata_qid: model.wikidata_qid.clone(),
isbn13: model.isbn13.clone(),
core_id: model.core_id.clone(),
+ arxiv_id: model.arxiv_id.clone(),
+ jstor_id: model.jstor_id.clone(),
volume: model.volume.clone(),
issue: model.issue.clone(),
pages: model.pages.clone(),
@@ -1983,6 +2064,7 @@ impl EntityCrud for ReleaseEntity {
},
publisher: model.publisher.clone(),
language: model.language.clone(),
+ license_slug: model.license_slug.clone(),
extra_json: model.extra.clone()
})
})
@@ -1991,34 +2073,32 @@ impl EntityCrud for ReleaseEntity {
.returning(release_rev::id)
.get_results(conn)?;
- let mut release_ref_rows: Vec<ReleaseRefNewRow> = vec![];
+ let mut release_ref_rows: Vec<ReleaseRefRow> = vec![];
let mut release_contrib_rows: Vec<ReleaseContribNewRow> = vec![];
let mut abstract_rows: Vec<AbstractsRow> = vec![];
let mut release_abstract_rows: Vec<ReleaseRevAbstractNewRow> = vec![];
for (model, rev_id) in models.iter().zip(rev_ids.iter()) {
+ // We didn't know the release_rev id to insert here, so need to re-iterate over refs
match &model.refs {
None => (),
Some(ref_list) => {
- let these_ref_rows: Vec<ReleaseRefNewRow> = ref_list
+ let these_ref_rows: Vec<ReleaseRefRow> = ref_list
.iter()
- .map(|r| {
- Ok(ReleaseRefNewRow {
+ .enumerate()
+ .filter(|(_, r)| r.target_release_id.is_some())
+ .map(|(index, r)| {
+ Ok(ReleaseRefRow {
release_rev: *rev_id,
- target_release_ident_id: match r.target_release_id.clone() {
- None => None,
- Some(v) => Some(FatcatId::from_str(&v)?.to_uuid()),
- },
- index_val: r.index.map(|v| v as i32),
- key: r.key.clone(),
- container_name: r.container_name.clone(),
- year: r.year.map(|v| v as i32),
- title: r.title.clone(),
- locator: r.locator.clone(),
- extra_json: r.extra.clone(),
+ // unwrap() checked by is_some() filter
+ target_release_ident_id: FatcatId::from_str(
+ &r.target_release_id.clone().unwrap(),
+ )?
+ .to_uuid(),
+ index_val: index as i32,
})
})
- .collect::<Result<Vec<ReleaseRefNewRow>>>()?;
+ .collect::<Result<Vec<ReleaseRefRow>>>()?;
release_ref_rows.extend(these_ref_rows);
}
};
@@ -2038,6 +2118,7 @@ impl EntityCrud for ReleaseEntity {
raw_name: c.raw_name.clone(),
index_val: c.index.map(|v| v as i32),
role: c.role.clone(),
+ raw_affiliation: c.raw_affiliation.clone(),
extra_json: c.extra.clone(),
})
})
@@ -2053,7 +2134,7 @@ impl EntityCrud for ReleaseEntity {
.iter()
.filter(|ea| ea.content.is_some())
.map(|c| AbstractsRow {
- sha1: Sha1::from(c.content.clone().unwrap()).hexdigest(),
+ sha1: Sha1::from(c.content.as_ref().unwrap()).hexdigest(),
content: c.content.clone().unwrap(),
})
.collect();