diff options
Diffstat (limited to 'rust/src/entity_crud.rs')
-rw-r--r-- | rust/src/entity_crud.rs | 175 |
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(); |