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;
|
return;
|
||||||
}
|
}
|
||||||
// Setup a new document
|
// Setup a new document
|
||||||
let mut doc = Document::new(thg, val);
|
let mut doc = Document::new(thg, &val);
|
||||||
|
|
||||||
// Process the document
|
// Process the document
|
||||||
let res = match self.stmt {
|
let res = match self.stmt {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn admit(
|
pub async fn admit(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &Runtime,
|
_ctx: &Runtime,
|
||||||
|
@ -17,19 +17,19 @@ impl Document {
|
||||||
Some(_) => Ok(()),
|
Some(_) => Ok(()),
|
||||||
None => match stm {
|
None => match stm {
|
||||||
Statement::Create(_) => Err(Error::CreateStatementError {
|
Statement::Create(_) => Err(Error::CreateStatementError {
|
||||||
value: self.initial.clone(),
|
value: (*self.initial).clone(),
|
||||||
}),
|
}),
|
||||||
Statement::Update(_) => Err(Error::UpdateStatementError {
|
Statement::Update(_) => Err(Error::UpdateStatementError {
|
||||||
value: self.initial.clone(),
|
value: (*self.initial).clone(),
|
||||||
}),
|
}),
|
||||||
Statement::Relate(_) => Err(Error::RelateStatementError {
|
Statement::Relate(_) => Err(Error::RelateStatementError {
|
||||||
value: self.initial.clone(),
|
value: (*self.initial).clone(),
|
||||||
}),
|
}),
|
||||||
Statement::Delete(_) => Err(Error::DeleteStatementError {
|
Statement::Delete(_) => Err(Error::DeleteStatementError {
|
||||||
value: self.initial.clone(),
|
value: (*self.initial).clone(),
|
||||||
}),
|
}),
|
||||||
Statement::Insert(_) => Err(Error::InsertStatementError {
|
Statement::Insert(_) => Err(Error::InsertStatementError {
|
||||||
value: self.initial.clone(),
|
value: (*self.initial).clone(),
|
||||||
}),
|
}),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn allow(
|
pub async fn allow(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &Runtime,
|
_ctx: &Runtime,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn check(
|
pub async fn check(
|
||||||
&self,
|
&self,
|
||||||
ctx: &Runtime,
|
ctx: &Runtime,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn compute(
|
pub async fn compute(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Runtime,
|
ctx: &Runtime,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn create(
|
pub async fn create(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Runtime,
|
ctx: &Runtime,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn delete(
|
pub async fn delete(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Runtime,
|
ctx: &Runtime,
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
use crate::sql::thing::Thing;
|
use crate::sql::thing::Thing;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct Document {
|
pub struct Document<'a> {
|
||||||
pub(super) id: Option<Thing>,
|
pub(super) id: Option<Thing>,
|
||||||
pub(super) current: Value,
|
pub(super) current: Cow<'a, Value>,
|
||||||
pub(super) initial: Value,
|
pub(super) initial: Cow<'a, Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub fn new(id: Option<Thing>, val: Value) -> Document {
|
pub fn new(id: Option<Thing>, val: &'a Value) -> Self {
|
||||||
Document {
|
Document {
|
||||||
id,
|
id,
|
||||||
current: val.clone(),
|
current: Cow::Borrowed(val),
|
||||||
initial: val,
|
initial: Cow::Borrowed(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,8 @@ use crate::dbs::Runtime;
|
||||||
use crate::dbs::Statement;
|
use crate::dbs::Statement;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::value::Value;
|
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn empty(
|
pub async fn empty(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &Runtime,
|
_ctx: &Runtime,
|
||||||
|
@ -14,7 +13,7 @@ impl Document {
|
||||||
_exe: &Executor<'_>,
|
_exe: &Executor<'_>,
|
||||||
_stm: &Statement<'_>,
|
_stm: &Statement<'_>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match self.id.is_some() && self.current == Value::None {
|
match self.id.is_some() && self.current.is_none() {
|
||||||
true => Err(Error::IgnoreError),
|
true => Err(Error::IgnoreError),
|
||||||
false => Ok(()),
|
false => Ok(()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn erase(
|
pub async fn erase(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Runtime,
|
ctx: &Runtime,
|
||||||
|
@ -13,6 +13,6 @@ impl Document {
|
||||||
exe: &Executor<'_>,
|
exe: &Executor<'_>,
|
||||||
_stm: &Statement<'_>,
|
_stm: &Statement<'_>,
|
||||||
) -> Result<(), Error> {
|
) -> 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::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn event(
|
pub async fn event(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &Runtime,
|
_ctx: &Runtime,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn index(
|
pub async fn index(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &Runtime,
|
_ctx: &Runtime,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn insert(
|
pub async fn insert(
|
||||||
&mut self,
|
&mut self,
|
||||||
_ctx: &Runtime,
|
_ctx: &Runtime,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn lives(
|
pub async fn lives(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &Runtime,
|
_ctx: &Runtime,
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::sql::data::Data;
|
||||||
use crate::sql::operator::Operator;
|
use crate::sql::operator::Operator;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn merge(
|
pub async fn merge(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Runtime,
|
ctx: &Runtime,
|
||||||
|
@ -25,7 +25,7 @@ impl Document {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
// Set default field values
|
// 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
|
// Check for a data clause
|
||||||
match data {
|
match data {
|
||||||
// The statement has a data clause
|
// The statement has a data clause
|
||||||
|
@ -35,26 +35,36 @@ impl Document {
|
||||||
let v = x.2.compute(ctx, opt, exe, Some(&self.current)).await?;
|
let v = x.2.compute(ctx, opt, exe, Some(&self.current)).await?;
|
||||||
match x.1 {
|
match x.1 {
|
||||||
Operator::Equal => match v {
|
Operator::Equal => match v {
|
||||||
Value::Void => self.current.del(ctx, opt, exe, &x.0).await?,
|
Value::Void => {
|
||||||
_ => self.current.set(ctx, opt, exe, &x.0, v).await?,
|
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::Inc => {
|
||||||
Operator::Dec => self.current.decrement(ctx, opt, exe, &x.0, v).await?,
|
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!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Data::PatchExpression(v) => self.current.patch(ctx, opt, exe, v).await?,
|
Data::PatchExpression(v) => self.current.to_mut().patch(ctx, opt, exe, v).await?,
|
||||||
Data::MergeExpression(v) => self.current.merge(ctx, opt, exe, v).await?,
|
Data::MergeExpression(v) => self.current.to_mut().merge(ctx, opt, exe, v).await?,
|
||||||
Data::ReplaceExpression(v) => self.current.replace(ctx, opt, exe, v).await?,
|
Data::ReplaceExpression(v) => {
|
||||||
Data::ContentExpression(v) => self.current.replace(ctx, opt, exe, v).await?,
|
self.current.to_mut().replace(ctx, opt, exe, v).await?
|
||||||
|
}
|
||||||
|
Data::ContentExpression(v) => {
|
||||||
|
self.current.to_mut().replace(ctx, opt, exe, v).await?
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
// No data clause has been set
|
// No data clause has been set
|
||||||
None => (),
|
None => (),
|
||||||
};
|
};
|
||||||
// Set default field values
|
// 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
|
// Set ASSERT and VALUE clauses
|
||||||
// todo!();
|
// todo!();
|
||||||
// Delete non-defined FIELDs
|
// Delete non-defined FIELDs
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::sql::idiom::Idiom;
|
||||||
use crate::sql::output::Output;
|
use crate::sql::output::Output;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn pluck(
|
pub async fn pluck(
|
||||||
&self,
|
&self,
|
||||||
ctx: &Runtime,
|
ctx: &Runtime,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn relate(
|
pub async fn relate(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Runtime,
|
ctx: &Runtime,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn select(
|
pub async fn select(
|
||||||
&self,
|
&self,
|
||||||
ctx: &Runtime,
|
ctx: &Runtime,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn store(
|
pub async fn store(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &Runtime,
|
_ctx: &Runtime,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::dbs::Statement;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn table(
|
pub async fn table(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &Runtime,
|
_ctx: &Runtime,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
|
||||||
impl Document {
|
impl<'a> Document<'a> {
|
||||||
pub async fn update(
|
pub async fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Runtime,
|
ctx: &Runtime,
|
||||||
|
|
Loading…
Reference in a new issue