Ensure undefined fields are removed in schemafull mode

This commit is contained in:
Tobie Morgan Hitchcock 2022-07-04 17:54:43 +01:00
parent 59d7e733eb
commit 6c5ddbf70f
7 changed files with 69 additions and 0 deletions

45
lib/src/doc/clean.rs Normal file
View file

@ -0,0 +1,45 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::Transaction;
use crate::doc::Document;
use crate::err::Error;
use crate::sql::idiom::Idiom;
impl<'a> Document<'a> {
pub async fn clean(
&mut self,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Get the table
let tb = self.tb(opt, txn).await?;
// This table is schemafull
if tb.full {
// Create a vector to store the keys
let mut keys: Vec<Idiom> = vec![];
// Loop through all field statements
for fd in self.fd(opt, txn).await?.iter() {
// Loop over this field in the document
for k in self.current.each(&fd.name).into_iter() {
keys.push(k);
}
// Loop over every field in the document
for k in self.current.every().iter() {
if !keys.contains(k) {
match k {
k if k.is_id() => continue,
k if k.is_in() => continue,
k if k.is_out() => continue,
k => self.current.to_mut().del(ctx, opt, txn, k).await?,
}
}
}
}
}
// Carry on
Ok(())
}
}

View file

@ -20,6 +20,8 @@ impl<'a> Document<'a> {
self.alter(ctx, opt, txn, stm).await?;
// Merge fields data
self.field(ctx, opt, txn, stm).await?;
// Clean fields data
self.clean(ctx, opt, txn, stm).await?;
// Check if allowed
self.allow(ctx, opt, txn, stm).await?;
// Store index data

View file

@ -24,6 +24,8 @@ impl<'a> Document<'a> {
self.merge(ctx, opt, txn, stm).await?;
// Merge fields data
self.field(ctx, opt, txn, stm).await?;
// Clean fields data
self.clean(ctx, opt, txn, stm).await?;
// Check if allowed
self.allow(ctx, opt, txn, stm).await?;
// Store index data
@ -47,6 +49,8 @@ impl<'a> Document<'a> {
self.alter(ctx, opt, txn, stm).await?;
// Merge fields data
self.field(ctx, opt, txn, stm).await?;
// Clean fields data
self.clean(ctx, opt, txn, stm).await?;
// Check if allowed
self.allow(ctx, opt, txn, stm).await?;
// Store index data

View file

@ -6,6 +6,7 @@ mod compute;
mod allow;
mod alter;
mod check;
mod clean;
mod create;
mod delete;
mod document;

View file

@ -20,6 +20,8 @@ impl<'a> Document<'a> {
self.alter(ctx, opt, txn, stm).await?;
// Merge fields data
self.field(ctx, opt, txn, stm).await?;
// Clean fields data
self.clean(ctx, opt, txn, stm).await?;
// Check if allowed
self.allow(ctx, opt, txn, stm).await?;
// Store record edges

View file

@ -22,6 +22,8 @@ impl<'a> Document<'a> {
self.alter(ctx, opt, txn, stm).await?;
// Merge fields data
self.field(ctx, opt, txn, stm).await?;
// Clean fields data
self.clean(ctx, opt, txn, stm).await?;
// Check if allowed
self.allow(ctx, opt, txn, stm).await?;
// Store index data

View file

@ -6,6 +6,7 @@ use crate::sql::common::commas;
use crate::sql::error::IResult;
use crate::sql::part::Next;
use crate::sql::part::{all, field, first, graph, index, last, part, thing, Part};
use crate::sql::paths::{ID, IN, OUT};
use crate::sql::value::Value;
use nom::branch::alt;
use nom::multi::separated_list1;
@ -77,6 +78,18 @@ impl Idiom {
.collect::<Vec<_>>()
.into()
}
// Check if this expression an 'id' field
pub(crate) fn is_id(&self) -> bool {
self.0.len() == 1 && self.0[0].eq(&ID[0])
}
// Check if this expression an 'in' field
pub(crate) fn is_in(&self) -> bool {
self.0.len() == 1 && self.0[0].eq(&IN[0])
}
// Check if this expression an 'out' field
pub(crate) fn is_out(&self) -> bool {
self.0.len() == 1 && self.0[0].eq(&OUT[0])
}
// Check if this is an expression with multiple yields
pub(crate) fn is_multi_yield(&self) -> bool {
self.iter().any(Self::split_multi_yield)