Ensure graph edges are purged correctly when deleted
This commit is contained in:
parent
27f011d13c
commit
20c4e03446
8 changed files with 70 additions and 22 deletions
|
@ -12,6 +12,7 @@ use crate::sql::part::Part;
|
|||
use crate::sql::table::Table;
|
||||
use crate::sql::thing::Thing;
|
||||
use crate::sql::value::Value;
|
||||
use async_recursion::async_recursion;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeMap;
|
||||
use std::mem;
|
||||
|
@ -329,6 +330,7 @@ impl Iterator {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
#[cfg_attr(not(feature = "parallel"), async_recursion(?Send))]
|
||||
async fn iterate(
|
||||
&mut self,
|
||||
ctx: &Context<'_>,
|
||||
|
@ -345,6 +347,7 @@ impl Iterator {
|
|||
}
|
||||
|
||||
#[cfg(feature = "parallel")]
|
||||
#[cfg_attr(feature = "parallel", async_recursion)]
|
||||
async fn iterate(
|
||||
&mut self,
|
||||
ctx: &Context<'_>,
|
||||
|
|
|
@ -5,12 +5,14 @@ use crate::dbs::Transaction;
|
|||
use crate::dbs::Workable;
|
||||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
use crate::sql::paths::IN;
|
||||
use crate::sql::paths::OUT;
|
||||
use crate::sql::Dir;
|
||||
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn edges(
|
||||
&self,
|
||||
_ctx: &Context<'_>,
|
||||
&mut self,
|
||||
ctx: &Context<'_>,
|
||||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
_stm: &Statement<'_>,
|
||||
|
@ -27,18 +29,23 @@ impl<'a> Document<'a> {
|
|||
let rid = self.id.as_ref().unwrap();
|
||||
// Store the record edges
|
||||
if let Workable::Relate(l, r) = &self.extras {
|
||||
// Get temporary edge references
|
||||
let (ref o, ref i) = (Dir::Out, Dir::In);
|
||||
// Store the left pointer edge
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &l.tb, &l.id, &Dir::Out, rid);
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &l.tb, &l.id, o, rid);
|
||||
run.set(key, vec![]).await?;
|
||||
// Store the left inner edge
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, &Dir::In, l);
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, i, l);
|
||||
run.set(key, vec![]).await?;
|
||||
// Store the right inner edge
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, &Dir::Out, r);
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, o, r);
|
||||
run.set(key, vec![]).await?;
|
||||
// Store the right pointer edge
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &r.tb, &r.id, &Dir::In, rid);
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &r.tb, &r.id, i, rid);
|
||||
run.set(key, vec![]).await?;
|
||||
// Store the edges on the record
|
||||
self.current.to_mut().set(ctx, opt, txn, &*IN, l.clone().into()).await?;
|
||||
self.current.to_mut().set(ctx, opt, txn, &*OUT, r.clone().into()).await?;
|
||||
}
|
||||
// Carry on
|
||||
Ok(())
|
||||
|
|
|
@ -4,11 +4,18 @@ use crate::dbs::Statement;
|
|||
use crate::dbs::Transaction;
|
||||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
use crate::sql::dir::Dir;
|
||||
use crate::sql::edges::Edges;
|
||||
use crate::sql::paths::IN;
|
||||
use crate::sql::paths::OUT;
|
||||
use crate::sql::statements::DeleteStatement;
|
||||
use crate::sql::table::Tables;
|
||||
use crate::sql::value::{Value, Values};
|
||||
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn purge(
|
||||
&self,
|
||||
_ctx: &Context<'_>,
|
||||
ctx: &Context<'_>,
|
||||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
_stm: &Statement<'_>,
|
||||
|
@ -30,10 +37,40 @@ impl<'a> Document<'a> {
|
|||
// Purge the record data
|
||||
let key = crate::key::thing::new(opt.ns(), opt.db(), &rid.tb, &rid.id);
|
||||
run.del(key).await?;
|
||||
// Remove the graph data
|
||||
let beg = crate::key::graph::prefix(opt.ns(), opt.db(), &rid.tb, &rid.id);
|
||||
let end = crate::key::graph::suffix(opt.ns(), opt.db(), &rid.tb, &rid.id);
|
||||
run.delr(beg..end, u32::MAX).await?;
|
||||
// Purge the record edges
|
||||
match (self.initial.pick(&*IN), self.initial.pick(&*OUT)) {
|
||||
(Value::Thing(ref l), Value::Thing(ref r)) => {
|
||||
// Get temporary edge references
|
||||
let (ref o, ref i) = (Dir::Out, Dir::In);
|
||||
// Purge the left pointer edge
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &l.tb, &l.id, o, rid);
|
||||
run.del(key).await?;
|
||||
// Purge the left inner edge
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, i, l);
|
||||
run.del(key).await?;
|
||||
// Purge the right inner edge
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, o, r);
|
||||
run.del(key).await?;
|
||||
// Purge the right pointer edge
|
||||
let key = crate::key::graph::new(opt.ns(), opt.db(), &r.tb, &r.id, i, rid);
|
||||
run.del(key).await?;
|
||||
}
|
||||
_ => {
|
||||
// Release the transaction
|
||||
drop(run);
|
||||
// Setup the delete statement
|
||||
let stm = DeleteStatement {
|
||||
what: Values(vec![Value::from(Edges {
|
||||
dir: Dir::Both,
|
||||
from: rid.clone(),
|
||||
what: Tables::default(),
|
||||
})]),
|
||||
..DeleteStatement::default()
|
||||
};
|
||||
// Execute the delete statement
|
||||
stm.compute(ctx, opt, txn, None).await?;
|
||||
}
|
||||
}
|
||||
// Carry on
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ pub(crate) mod output;
|
|||
pub(crate) mod param;
|
||||
pub(crate) mod parser;
|
||||
pub(crate) mod part;
|
||||
pub(crate) mod paths;
|
||||
pub(crate) mod permission;
|
||||
pub(crate) mod query;
|
||||
pub(crate) mod regex;
|
||||
|
|
8
lib/src/sql/paths.rs
Normal file
8
lib/src/sql/paths.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use crate::sql::part::Part;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
pub static ID: Lazy<[Part; 1]> = Lazy::new(|| [Part::from("id")]);
|
||||
|
||||
pub static IN: Lazy<[Part; 1]> = Lazy::new(|| [Part::from("in")]);
|
||||
|
||||
pub static OUT: Lazy<[Part; 1]> = Lazy::new(|| [Part::from("out")]);
|
|
@ -2,12 +2,9 @@ use crate::ctx::Context;
|
|||
use crate::dbs::Options;
|
||||
use crate::dbs::Transaction;
|
||||
use crate::err::Error;
|
||||
use crate::sql::part::Part;
|
||||
use crate::sql::paths::ID;
|
||||
use crate::sql::thing::Thing;
|
||||
use crate::sql::value::Value;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
static ID: Lazy<[Part; 1]> = Lazy::new(|| [Part::from("id")]);
|
||||
|
||||
impl Value {
|
||||
pub async fn def(
|
||||
|
|
|
@ -6,13 +6,11 @@ use crate::sql::edges::Edges;
|
|||
use crate::sql::field::{Field, Fields};
|
||||
use crate::sql::part::Next;
|
||||
use crate::sql::part::Part;
|
||||
use crate::sql::paths::ID;
|
||||
use crate::sql::statements::select::SelectStatement;
|
||||
use crate::sql::value::{Value, Values};
|
||||
use async_recursion::async_recursion;
|
||||
use futures::future::try_join_all;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
static ID: Lazy<[Part; 1]> = Lazy::new(|| [Part::from("id")]);
|
||||
|
||||
impl Value {
|
||||
#[cfg_attr(feature = "parallel", async_recursion)]
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
use crate::err::Error;
|
||||
use crate::sql::id::Id;
|
||||
use crate::sql::part::Part;
|
||||
use crate::sql::paths::ID;
|
||||
use crate::sql::table::Table;
|
||||
use crate::sql::thing::Thing;
|
||||
use crate::sql::value::Value;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
static ID: Lazy<[Part; 1]> = Lazy::new(|| [Part::from("id")]);
|
||||
|
||||
impl Value {
|
||||
pub fn retable(&self, val: &Table) -> Result<Thing, Error> {
|
||||
|
|
Loading…
Reference in a new issue