Use copy-on-write semantics for document values
Instead of blindly cloning document values (even if we don't need to mutate them), we now use copy-on-write semantics to only create a copy if we need to update a document value. This improves performance, especially when selecting documents.
This commit is contained in:
parent
5e25435b9a
commit
fbd924fbac
21 changed files with 55 additions and 45 deletions
|
@ -178,7 +178,7 @@ impl<'a> Iterator<'a> {
|
|||
return;
|
||||
}
|
||||
// Setup a new document
|
||||
let mut doc = Document::new(thg, val);
|
||||
let mut doc = Document::new(thg, &val);
|
||||
|
||||
// Process the document
|
||||
let res = match self.stmt {
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
|||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn admit(
|
||||
&self,
|
||||
_ctx: &Runtime,
|
||||
|
@ -17,19 +17,19 @@ impl Document {
|
|||
Some(_) => Ok(()),
|
||||
None => match stm {
|
||||
Statement::Create(_) => Err(Error::CreateStatementError {
|
||||
value: self.initial.clone(),
|
||||
value: (*self.initial).clone(),
|
||||
}),
|
||||
Statement::Update(_) => Err(Error::UpdateStatementError {
|
||||
value: self.initial.clone(),
|
||||
value: (*self.initial).clone(),
|
||||
}),
|
||||
Statement::Relate(_) => Err(Error::RelateStatementError {
|
||||
value: self.initial.clone(),
|
||||
value: (*self.initial).clone(),
|
||||
}),
|
||||
Statement::Delete(_) => Err(Error::DeleteStatementError {
|
||||
value: self.initial.clone(),
|
||||
value: (*self.initial).clone(),
|
||||
}),
|
||||
Statement::Insert(_) => Err(Error::InsertStatementError {
|
||||
value: self.initial.clone(),
|
||||
value: (*self.initial).clone(),
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
|||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn allow(
|
||||
&self,
|
||||
_ctx: &Runtime,
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
|||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn check(
|
||||
&self,
|
||||
ctx: &Runtime,
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
|||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn compute(
|
||||
&mut self,
|
||||
ctx: &Runtime,
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
|||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn create(
|
||||
&mut self,
|
||||
ctx: &Runtime,
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
|||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn delete(
|
||||
&mut self,
|
||||
ctx: &Runtime,
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
use crate::sql::thing::Thing;
|
||||
use crate::sql::value::Value;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Document {
|
||||
pub struct Document<'a> {
|
||||
pub(super) id: Option<Thing>,
|
||||
pub(super) current: Value,
|
||||
pub(super) initial: Value,
|
||||
pub(super) current: Cow<'a, Value>,
|
||||
pub(super) initial: Cow<'a, Value>,
|
||||
}
|
||||
|
||||
impl Document {
|
||||
pub fn new(id: Option<Thing>, val: Value) -> Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub fn new(id: Option<Thing>, val: &'a Value) -> Self {
|
||||
Document {
|
||||
id,
|
||||
current: val.clone(),
|
||||
initial: val,
|
||||
current: Cow::Borrowed(val),
|
||||
initial: Cow::Borrowed(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ use crate::dbs::Runtime;
|
|||
use crate::dbs::Statement;
|
||||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn empty(
|
||||
&self,
|
||||
_ctx: &Runtime,
|
||||
|
@ -14,7 +13,7 @@ impl Document {
|
|||
_exe: &Executor<'_>,
|
||||
_stm: &Statement<'_>,
|
||||
) -> Result<(), Error> {
|
||||
match self.id.is_some() && self.current == Value::None {
|
||||
match self.id.is_some() && self.current.is_none() {
|
||||
true => Err(Error::IgnoreError),
|
||||
false => Ok(()),
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
|||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn erase(
|
||||
&mut self,
|
||||
ctx: &Runtime,
|
||||
|
@ -13,6 +13,6 @@ impl Document {
|
|||
exe: &Executor<'_>,
|
||||
_stm: &Statement<'_>,
|
||||
) -> Result<(), Error> {
|
||||
self.current.clear(ctx, opt, exe).await
|
||||
self.current.to_mut().clear(ctx, opt, exe).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
|||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn event(
|
||||
&self,
|
||||
_ctx: &Runtime,
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
|||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn index(
|
||||
&self,
|
||||
_ctx: &Runtime,
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
|||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn insert(
|
||||
&mut self,
|
||||
_ctx: &Runtime,
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
|||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn lives(
|
||||
&self,
|
||||
_ctx: &Runtime,
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::sql::data::Data;
|
|||
use crate::sql::operator::Operator;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn merge(
|
||||
&mut self,
|
||||
ctx: &Runtime,
|
||||
|
@ -25,7 +25,7 @@ impl Document {
|
|||
_ => unreachable!(),
|
||||
};
|
||||
// Set default field values
|
||||
self.current.def(ctx, opt, exe, id).await?;
|
||||
self.current.to_mut().def(ctx, opt, exe, id).await?;
|
||||
// Check for a data clause
|
||||
match data {
|
||||
// The statement has a data clause
|
||||
|
@ -35,26 +35,36 @@ impl Document {
|
|||
let v = x.2.compute(ctx, opt, exe, Some(&self.current)).await?;
|
||||
match x.1 {
|
||||
Operator::Equal => match v {
|
||||
Value::Void => self.current.del(ctx, opt, exe, &x.0).await?,
|
||||
_ => self.current.set(ctx, opt, exe, &x.0, v).await?,
|
||||
Value::Void => {
|
||||
self.current.to_mut().del(ctx, opt, exe, &x.0).await?
|
||||
}
|
||||
_ => self.current.to_mut().set(ctx, opt, exe, &x.0, v).await?,
|
||||
},
|
||||
Operator::Inc => self.current.increment(ctx, opt, exe, &x.0, v).await?,
|
||||
Operator::Dec => self.current.decrement(ctx, opt, exe, &x.0, v).await?,
|
||||
Operator::Inc => {
|
||||
self.current.to_mut().increment(ctx, opt, exe, &x.0, v).await?
|
||||
}
|
||||
Operator::Dec => {
|
||||
self.current.to_mut().decrement(ctx, opt, exe, &x.0, v).await?
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Data::PatchExpression(v) => self.current.patch(ctx, opt, exe, v).await?,
|
||||
Data::MergeExpression(v) => self.current.merge(ctx, opt, exe, v).await?,
|
||||
Data::ReplaceExpression(v) => self.current.replace(ctx, opt, exe, v).await?,
|
||||
Data::ContentExpression(v) => self.current.replace(ctx, opt, exe, v).await?,
|
||||
Data::PatchExpression(v) => self.current.to_mut().patch(ctx, opt, exe, v).await?,
|
||||
Data::MergeExpression(v) => self.current.to_mut().merge(ctx, opt, exe, v).await?,
|
||||
Data::ReplaceExpression(v) => {
|
||||
self.current.to_mut().replace(ctx, opt, exe, v).await?
|
||||
}
|
||||
Data::ContentExpression(v) => {
|
||||
self.current.to_mut().replace(ctx, opt, exe, v).await?
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
// No data clause has been set
|
||||
None => (),
|
||||
};
|
||||
// Set default field values
|
||||
self.current.def(ctx, opt, exe, id).await?;
|
||||
self.current.to_mut().def(ctx, opt, exe, id).await?;
|
||||
// Set ASSERT and VALUE clauses
|
||||
// todo!();
|
||||
// Delete non-defined FIELDs
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::sql::idiom::Idiom;
|
|||
use crate::sql::output::Output;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn pluck(
|
||||
&self,
|
||||
ctx: &Runtime,
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
|||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn relate(
|
||||
&mut self,
|
||||
ctx: &Runtime,
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
|||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn select(
|
||||
&self,
|
||||
ctx: &Runtime,
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
|||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn store(
|
||||
&self,
|
||||
_ctx: &Runtime,
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
|||
use crate::doc::Document;
|
||||
use crate::err::Error;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn table(
|
||||
&self,
|
||||
_ctx: &Runtime,
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
|||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Document {
|
||||
impl<'a> Document<'a> {
|
||||
pub async fn update(
|
||||
&mut self,
|
||||
ctx: &Runtime,
|
||||
|
|
Loading…
Reference in a new issue