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::table::Table;
|
||||||
use crate::sql::thing::Thing;
|
use crate::sql::thing::Thing;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
use async_recursion::async_recursion;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -329,6 +330,7 @@ impl Iterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "parallel"))]
|
#[cfg(not(feature = "parallel"))]
|
||||||
|
#[cfg_attr(not(feature = "parallel"), async_recursion(?Send))]
|
||||||
async fn iterate(
|
async fn iterate(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
|
@ -345,6 +347,7 @@ impl Iterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "parallel")]
|
#[cfg(feature = "parallel")]
|
||||||
|
#[cfg_attr(feature = "parallel", async_recursion)]
|
||||||
async fn iterate(
|
async fn iterate(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
|
|
|
@ -5,12 +5,14 @@ use crate::dbs::Transaction;
|
||||||
use crate::dbs::Workable;
|
use crate::dbs::Workable;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
use crate::sql::paths::IN;
|
||||||
|
use crate::sql::paths::OUT;
|
||||||
use crate::sql::Dir;
|
use crate::sql::Dir;
|
||||||
|
|
||||||
impl<'a> Document<'a> {
|
impl<'a> Document<'a> {
|
||||||
pub async fn edges(
|
pub async fn edges(
|
||||||
&self,
|
&mut self,
|
||||||
_ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
opt: &Options,
|
opt: &Options,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
_stm: &Statement<'_>,
|
_stm: &Statement<'_>,
|
||||||
|
@ -27,18 +29,23 @@ impl<'a> Document<'a> {
|
||||||
let rid = self.id.as_ref().unwrap();
|
let rid = self.id.as_ref().unwrap();
|
||||||
// Store the record edges
|
// Store the record edges
|
||||||
if let Workable::Relate(l, r) = &self.extras {
|
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
|
// 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?;
|
run.set(key, vec![]).await?;
|
||||||
// Store the left inner edge
|
// 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?;
|
run.set(key, vec![]).await?;
|
||||||
// Store the right inner edge
|
// 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?;
|
run.set(key, vec![]).await?;
|
||||||
// Store the right pointer edge
|
// 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?;
|
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
|
// Carry on
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -4,11 +4,18 @@ use crate::dbs::Statement;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
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> {
|
impl<'a> Document<'a> {
|
||||||
pub async fn purge(
|
pub async fn purge(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
opt: &Options,
|
opt: &Options,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
_stm: &Statement<'_>,
|
_stm: &Statement<'_>,
|
||||||
|
@ -30,10 +37,40 @@ impl<'a> Document<'a> {
|
||||||
// Purge the record data
|
// Purge the record data
|
||||||
let key = crate::key::thing::new(opt.ns(), opt.db(), &rid.tb, &rid.id);
|
let key = crate::key::thing::new(opt.ns(), opt.db(), &rid.tb, &rid.id);
|
||||||
run.del(key).await?;
|
run.del(key).await?;
|
||||||
// Remove the graph data
|
// Purge the record edges
|
||||||
let beg = crate::key::graph::prefix(opt.ns(), opt.db(), &rid.tb, &rid.id);
|
match (self.initial.pick(&*IN), self.initial.pick(&*OUT)) {
|
||||||
let end = crate::key::graph::suffix(opt.ns(), opt.db(), &rid.tb, &rid.id);
|
(Value::Thing(ref l), Value::Thing(ref r)) => {
|
||||||
run.delr(beg..end, u32::MAX).await?;
|
// 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
|
// Carry on
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub(crate) mod output;
|
||||||
pub(crate) mod param;
|
pub(crate) mod param;
|
||||||
pub(crate) mod parser;
|
pub(crate) mod parser;
|
||||||
pub(crate) mod part;
|
pub(crate) mod part;
|
||||||
|
pub(crate) mod paths;
|
||||||
pub(crate) mod permission;
|
pub(crate) mod permission;
|
||||||
pub(crate) mod query;
|
pub(crate) mod query;
|
||||||
pub(crate) mod regex;
|
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::Options;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::part::Part;
|
use crate::sql::paths::ID;
|
||||||
use crate::sql::thing::Thing;
|
use crate::sql::thing::Thing;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
static ID: Lazy<[Part; 1]> = Lazy::new(|| [Part::from("id")]);
|
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub async fn def(
|
pub async fn def(
|
||||||
|
|
|
@ -6,13 +6,11 @@ use crate::sql::edges::Edges;
|
||||||
use crate::sql::field::{Field, Fields};
|
use crate::sql::field::{Field, Fields};
|
||||||
use crate::sql::part::Next;
|
use crate::sql::part::Next;
|
||||||
use crate::sql::part::Part;
|
use crate::sql::part::Part;
|
||||||
|
use crate::sql::paths::ID;
|
||||||
use crate::sql::statements::select::SelectStatement;
|
use crate::sql::statements::select::SelectStatement;
|
||||||
use crate::sql::value::{Value, Values};
|
use crate::sql::value::{Value, Values};
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use futures::future::try_join_all;
|
use futures::future::try_join_all;
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
static ID: Lazy<[Part; 1]> = Lazy::new(|| [Part::from("id")]);
|
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
#[cfg_attr(feature = "parallel", async_recursion)]
|
#[cfg_attr(feature = "parallel", async_recursion)]
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::id::Id;
|
use crate::sql::id::Id;
|
||||||
use crate::sql::part::Part;
|
use crate::sql::paths::ID;
|
||||||
use crate::sql::table::Table;
|
use crate::sql::table::Table;
|
||||||
use crate::sql::thing::Thing;
|
use crate::sql::thing::Thing;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
static ID: Lazy<[Part; 1]> = Lazy::new(|| [Part::from("id")]);
|
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn retable(&self, val: &Table) -> Result<Thing, Error> {
|
pub fn retable(&self, val: &Table) -> Result<Thing, Error> {
|
||||||
|
|
Loading…
Reference in a new issue