fix: self referencing database
This commit is contained in:
parent
0577e962c3
commit
0c1cdbed7a
|
|
@ -693,6 +693,44 @@ impl PublishCollabDuplicator {
|
|||
.duplicated_refs
|
||||
.insert(pub_db_id.clone(), Some(new_db_id.clone()));
|
||||
|
||||
{
|
||||
// assign new id to all views of database.
|
||||
// this will mark the database as duplicated
|
||||
let txn = db_collab.context.transact();
|
||||
let mut db_views = db_body.views.get_all_views(&txn);
|
||||
let mut new_db_view_ids: Vec<String> = Vec::with_capacity(db_views.len());
|
||||
for db_view in db_views.iter_mut() {
|
||||
let new_db_view_id = if db_view.id == publish_view_id {
|
||||
self
|
||||
.duplicated_db_main_view
|
||||
.insert(pub_db_id.clone(), new_view_id.clone());
|
||||
new_view_id.clone()
|
||||
} else {
|
||||
gen_view_id()
|
||||
};
|
||||
self
|
||||
.duplicated_db_view
|
||||
.insert(db_view.id.clone(), new_db_view_id.clone());
|
||||
|
||||
new_db_view_ids.push(new_db_view_id);
|
||||
}
|
||||
|
||||
// Add this database as linked view
|
||||
self
|
||||
.workspace_databases
|
||||
.insert(new_db_id.clone(), new_db_view_ids);
|
||||
}
|
||||
|
||||
// assign new id to all rows of database.
|
||||
// this will mark the rows as duplicated
|
||||
for pub_row_id in published_db.database_row_collabs.keys() {
|
||||
// assign a new id for the row
|
||||
let dup_row_id = gen_row_id();
|
||||
self
|
||||
.duplicated_db_row
|
||||
.insert(pub_row_id.clone(), dup_row_id.to_string());
|
||||
}
|
||||
|
||||
{
|
||||
// handle row relations
|
||||
let mut txn = db_collab.context.transact_mut();
|
||||
|
|
@ -734,8 +772,12 @@ impl PublishCollabDuplicator {
|
|||
|
||||
// duplicate db collab rows
|
||||
for (pub_row_id, row_bin_data) in &published_db.database_row_collabs {
|
||||
// assign a new id for the row
|
||||
let dup_row_id = gen_row_id();
|
||||
let dup_row_id = self
|
||||
.duplicated_db_row
|
||||
.get(pub_row_id)
|
||||
.ok_or_else(|| AppError::RecordNotFound(format!("row not found: {}", pub_row_id)))?
|
||||
.clone();
|
||||
|
||||
let mut db_row_collab = collab_from_doc_state(row_bin_data.clone(), &dup_row_id)?;
|
||||
let mut db_row_body = DatabaseRowBody::open(pub_row_id.clone().into(), &mut db_row_collab)
|
||||
.map_err(|e| AppError::Unhandled(e.to_string()))?;
|
||||
|
|
@ -754,7 +796,7 @@ impl PublishCollabDuplicator {
|
|||
|
||||
// updates row id along with meta keys
|
||||
db_row_body
|
||||
.update_id(&mut txn, dup_row_id.clone())
|
||||
.update_id(&mut txn, dup_row_id.clone().into())
|
||||
.map_err(|e| AppError::Unhandled(format!("failed to update row id: {:?}", e)))?;
|
||||
|
||||
// duplicate row document if exists
|
||||
|
|
@ -860,34 +902,24 @@ impl PublishCollabDuplicator {
|
|||
dup_row_id.to_string(),
|
||||
(CollabType::DatabaseRow, db_row_ec_bytes),
|
||||
);
|
||||
self
|
||||
.duplicated_db_row
|
||||
.insert(pub_row_id.clone(), dup_row_id.to_string());
|
||||
}
|
||||
|
||||
// accumulate list of database views (Board, Cal, ...) to be linked to the database
|
||||
let mut new_db_view_ids: Vec<String> = vec![];
|
||||
{
|
||||
let mut txn = db_collab.context.transact_mut();
|
||||
db_body.root.insert(&mut txn, "id", new_db_id.clone());
|
||||
|
||||
let mut db_views = db_body.views.get_all_views(&txn);
|
||||
for db_view in db_views.iter_mut() {
|
||||
let new_db_view_id = if db_view.id == publish_view_id {
|
||||
self
|
||||
.duplicated_db_main_view
|
||||
.insert(pub_db_id.clone(), new_view_id.clone());
|
||||
new_view_id.clone()
|
||||
} else {
|
||||
gen_view_id()
|
||||
};
|
||||
self
|
||||
.duplicated_db_view
|
||||
.insert(db_view.id.clone(), new_db_view_id.clone());
|
||||
let new_db_view_id = self.duplicated_db_view.get(&db_view.id).ok_or_else(|| {
|
||||
AppError::Unhandled(format!(
|
||||
"view not found in duplicated_db_view: {}",
|
||||
db_view.id
|
||||
))
|
||||
})?;
|
||||
|
||||
db_view.id.clone_from(&new_db_view_id);
|
||||
db_view.id.clone_from(new_db_view_id);
|
||||
db_view.database_id.clone_from(&new_db_id);
|
||||
new_db_view_ids.push(db_view.id.clone());
|
||||
|
||||
// update all views's row's id
|
||||
for row_order in db_view.row_orders.iter_mut() {
|
||||
|
|
@ -917,11 +949,6 @@ impl PublishCollabDuplicator {
|
|||
.collabs_to_insert
|
||||
.insert(new_db_id.clone(), (CollabType::Database, db_encoded_collab));
|
||||
|
||||
// Add this database as linked view
|
||||
self
|
||||
.workspace_databases
|
||||
.insert(new_db_id.clone(), new_db_view_ids);
|
||||
|
||||
Ok((pub_db_id, new_db_id, false))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1304,6 +1304,88 @@ async fn duplicate_to_workspace_db_row_with_doc() {
|
|||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn duplicate_to_workspace_db_rel_self() {
|
||||
let client_1 = TestClient::new_user().await;
|
||||
let workspace_id = client_1.workspace_id().await;
|
||||
|
||||
// database with a row referencing itself
|
||||
// uuid must be fixed because the collab contains row data which reference itself
|
||||
let db_rel_self_view_id: uuid::Uuid = "18d72589-80d7-4041-9342-5d572facb7c9".parse().unwrap();
|
||||
let db_rel_self_metadata: PublishViewMetaData =
|
||||
serde_json::from_str(published_data::DB_REL_SELF_META).unwrap();
|
||||
let db_rel_self_blob = hex::decode(published_data::DB_REL_SELF_HEX).unwrap();
|
||||
|
||||
client_1
|
||||
.api_client
|
||||
.publish_collabs(
|
||||
&workspace_id,
|
||||
vec![PublishCollabItem {
|
||||
meta: PublishCollabMetadata {
|
||||
view_id: db_rel_self_view_id,
|
||||
publish_name: "db-rel-self".to_string(),
|
||||
metadata: db_rel_self_metadata.clone(),
|
||||
},
|
||||
data: db_rel_self_blob,
|
||||
}],
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let mut client_2 = TestClient::new_user().await;
|
||||
let workspace_id_2 = client_2.workspace_id().await;
|
||||
let fv = client_2
|
||||
.api_client
|
||||
.get_workspace_folder(&workspace_id_2, Some(5), None)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
client_2
|
||||
.api_client
|
||||
.duplicate_published_to_workspace(
|
||||
&workspace_id_2,
|
||||
&PublishedDuplicate {
|
||||
published_view_id: db_rel_self_view_id.to_string(),
|
||||
dest_view_id: fv.view_id, // use the root view
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let fv = client_2
|
||||
.api_client
|
||||
.get_workspace_folder(&workspace_id_2, Some(5), None)
|
||||
.await
|
||||
.unwrap();
|
||||
println!("{:#?}", fv);
|
||||
|
||||
let db_rel_self = fv
|
||||
.children
|
||||
.iter()
|
||||
.find(|v| v.name == "self_ref_db")
|
||||
.unwrap();
|
||||
|
||||
let db_rel_self_collab = client_2
|
||||
.get_db_collab_from_view(&workspace_id_2, &db_rel_self.view_id)
|
||||
.await;
|
||||
let txn = db_rel_self_collab.transact();
|
||||
let db_rel_self_body = DatabaseBody::from_collab(&db_rel_self_collab).unwrap();
|
||||
let database_id = db_rel_self_body.get_database_id(&txn);
|
||||
let all_fields = db_rel_self_body.fields.get_all_fields(&txn);
|
||||
let rel_fields = all_fields
|
||||
.iter()
|
||||
.map(|f| &f.type_options)
|
||||
.flat_map(|t| t.iter())
|
||||
.filter(|(k, _v)| **k == FieldType::Relation.type_id())
|
||||
.map(|(_k, v)| v)
|
||||
.flat_map(|v| v.iter())
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(rel_fields.len(), 1);
|
||||
assert_eq!(rel_fields[0].1.to_string(), database_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_database_id_and_row_ids(published_db_blob: &[u8]) -> (String, HashSet<String>) {
|
||||
let pub_db_data = serde_json::from_slice::<PublishDatabaseData>(published_db_blob).unwrap();
|
||||
let db_collab = collab_from_doc_state(pub_db_data.database_collab, "").unwrap();
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue