Move Transaction to Context ()

This commit is contained in:
Emmanuel Keller 2024-05-28 11:43:45 +01:00 committed by GitHub
parent 2b223d45ea
commit a9e075463d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
133 changed files with 1323 additions and 1879 deletions

View file

@ -3,13 +3,15 @@ use crate::ctx::reason::Reason;
use crate::dbs::capabilities::FuncTarget;
#[cfg(feature = "http")]
use crate::dbs::capabilities::NetTarget;
use crate::dbs::{Capabilities, Notification};
use crate::dbs::{Capabilities, Notification, Transaction};
use crate::err::Error;
use crate::idx::planner::executor::QueryExecutor;
use crate::idx::planner::{IterationStage, QueryPlanner};
use crate::idx::trees::store::IndexStores;
use crate::kvs;
use crate::sql::value::Value;
use channel::Sender;
use futures::lock::MutexLockFuture;
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt::{self, Debug};
@ -75,6 +77,8 @@ pub struct Context<'a> {
))]
// The temporary directory
temporary_directory: Option<Arc<PathBuf>>,
// An optional transaction
transaction: Option<Transaction>,
}
impl<'a> Default for Context<'a> {
@ -131,6 +135,7 @@ impl<'a> Context<'a> {
feature = "kv-speedb"
))]
temporary_directory,
transaction: None,
};
if let Some(timeout) = time_out {
ctx.add_timeout(timeout)?;
@ -160,6 +165,7 @@ impl<'a> Context<'a> {
feature = "kv-speedb"
))]
temporary_directory: None,
transaction: None,
}
}
@ -186,6 +192,7 @@ impl<'a> Context<'a> {
feature = "kv-speedb"
))]
temporary_directory: parent.temporary_directory.clone(),
transaction: parent.transaction.clone(),
}
}
@ -246,6 +253,19 @@ impl<'a> Context<'a> {
self.iteration_stage = Some(is);
}
pub(crate) fn set_transaction_mut(&mut self, txn: Transaction) {
self.transaction = Some(txn);
}
pub fn set_transaction(mut self, txn: Transaction) -> Self {
self.transaction = Some(txn);
self
}
pub(crate) fn tx_lock(&self) -> MutexLockFuture<'_, kvs::Transaction> {
self.transaction.as_ref().map(|txn| txn.lock()).unwrap_or_else(|| unreachable!())
}
/// Get the timeout for this operation, if any. This is useful for
/// checking if a long job should be started or not.
pub fn timeout(&self) -> Option<Duration> {

View file

@ -311,10 +311,10 @@ impl<'a> Executor<'a> {
true => Err(Error::TxFailure),
// The transaction began successfully
false => {
ctx.set_transaction_mut(self.txn());
// Check the statement
let txn = self.txn();
match stack
.enter(|stk| stm.compute(stk, &ctx, &opt, &txn, None))
.enter(|stk| stm.compute(stk, &ctx, &opt, None))
.finish()
.await
{
@ -384,12 +384,10 @@ impl<'a> Executor<'a> {
if let Err(err) = ctx.add_timeout(timeout) {
Err(err)
} else {
let txn = self.txn();
ctx.set_transaction_mut(self.txn());
// Process the statement
let res = stack
.enter(|stk| {
stm.compute(stk, &ctx, &opt, &txn, None)
})
.enter(|stk| stm.compute(stk, &ctx, &opt, None))
.finish()
.await;
// Catch statement timeout
@ -401,9 +399,9 @@ impl<'a> Executor<'a> {
}
// There is no timeout clause
None => {
let txn = self.txn();
ctx.set_transaction_mut(self.txn());
stack
.enter(|stk| stm.compute(stk, &ctx, &opt, &txn, None))
.enter(|stk| stm.compute(stk, &ctx, &opt, None))
.finish()
.await
}

View file

@ -1,7 +1,7 @@
use crate::ctx::Context;
use crate::dbs::plan::Explanation;
use crate::dbs::store::MemoryCollector;
use crate::dbs::{Options, Statement, Transaction};
use crate::dbs::{Options, Statement};
use crate::err::Error;
use crate::sql::function::OptimisedAggregate;
use crate::sql::value::{TryAdd, TryDiv, Value};
@ -63,7 +63,6 @@ impl GroupsCollector {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
obj: Value,
) -> Result<(), Error> {
@ -82,7 +81,7 @@ impl GroupsCollector {
.grp
.entry(arr)
.or_insert_with(|| self.base.iter().map(|a| a.new_instance()).collect());
Self::pushes(stk, ctx, opt, txn, agr, &self.idioms, obj).await?
Self::pushes(stk, ctx, opt, agr, &self.idioms, obj).await?
}
Ok(())
}
@ -91,14 +90,13 @@ impl GroupsCollector {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
agrs: &mut [Aggregator],
idioms: &[Idiom],
obj: Value,
) -> Result<(), Error> {
for (agr, idiom) in agrs.iter_mut().zip(idioms) {
let val = stk.run(|stk| obj.get(stk, ctx, opt, txn, None, idiom)).await?;
agr.push(stk, ctx, opt, txn, val).await?;
let val = stk.run(|stk| obj.get(stk, ctx, opt, None, idiom)).await?;
agr.push(stk, ctx, opt, val).await?;
}
Ok(())
}
@ -112,7 +110,6 @@ impl GroupsCollector {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<MemoryCollector, Error> {
let mut results = MemoryCollector::default();
@ -143,18 +140,16 @@ impl GroupsCollector {
let x = if matches!(a, OptimisedAggregate::None) {
// The aggregation is not optimised, let's compute it with the values
let vals = agr.take();
f.aggregate(vals)
.compute(stk, ctx, opt, txn, None)
.await?
f.aggregate(vals).compute(stk, ctx, opt, None).await?
} else {
// The aggregation is optimised, just get the value
agr.compute(a)?
};
obj.set(stk, ctx, opt, txn, idiom.as_ref(), x).await?;
obj.set(stk, ctx, opt, idiom.as_ref(), x).await?;
}
_ => {
let x = agr.take().first();
obj.set(stk, ctx, opt, txn, idiom.as_ref(), x).await?;
obj.set(stk, ctx, opt, idiom.as_ref(), x).await?;
}
}
}
@ -263,14 +258,13 @@ impl Aggregator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
val: Value,
) -> Result<(), Error> {
if let Some(ref mut c) = self.count {
*c += 1;
}
if let Some((ref f, ref mut c)) = self.count_function {
if f.aggregate(val.clone()).compute(stk, ctx, opt, txn, None).await?.is_truthy() {
if f.aggregate(val.clone()).compute(stk, ctx, opt, None).await?.is_truthy() {
*c += 1;
}
}

View file

@ -5,8 +5,8 @@ use crate::dbs::distinct::AsyncDistinct;
use crate::dbs::distinct::SyncDistinct;
use crate::dbs::plan::Plan;
use crate::dbs::result::Results;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::idx::planner::iterators::{IteratorRecord, IteratorRef};
@ -96,7 +96,6 @@ impl Iterator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
val: Value,
) -> Result<(), Error> {
@ -106,7 +105,7 @@ impl Iterator {
// There is a data clause so fetch a record id
Some(data) => match stm {
Statement::Create(_) => {
let id = match data.rid(stk, ctx, opt, txn).await? {
let id = match data.rid(stk, ctx, opt).await? {
// Generate a new id from the id field
Some(id) => id.generate(&v, false)?,
// Generate a new random table id
@ -135,7 +134,7 @@ impl Iterator {
// Check if there is a data clause
if let Some(data) = stm.data() {
// Check if there is an id field specified
if let Some(id) = data.rid(stk, ctx, opt, txn).await? {
if let Some(id) = data.rid(stk, ctx, opt).await? {
// Check to see the type of the id
match id {
// The id is a match, so don't error
@ -163,7 +162,7 @@ impl Iterator {
// Check if there is a data clause
if let Some(data) = stm.data() {
// Check if there is an id field specified
if let Some(id) = data.rid(stk, ctx, opt, txn).await? {
if let Some(id) = data.rid(stk, ctx, opt).await? {
return Err(Error::IdMismatch {
value: id.to_string(),
});
@ -184,7 +183,7 @@ impl Iterator {
// Check if there is a data clause
if let Some(data) = stm.data() {
// Check if there is an id field specified
if let Some(id) = data.rid(stk, ctx, opt, txn).await? {
if let Some(id) = data.rid(stk, ctx, opt).await? {
return Err(Error::IdMismatch {
value: id.to_string(),
});
@ -203,7 +202,7 @@ impl Iterator {
// Check if there is a data clause
if let Some(data) = stm.data() {
// Check if there is an id field specified
if let Some(id) = data.rid(stk, ctx, opt, txn).await? {
if let Some(id) = data.rid(stk, ctx, opt).await? {
return Err(Error::IdMismatch {
value: id.to_string(),
});
@ -216,7 +215,7 @@ impl Iterator {
// Check if there is a data clause
if let Some(data) = stm.data() {
// Check if there is an id field specified
if let Some(id) = data.rid(stk, ctx, opt, txn).await? {
if let Some(id) = data.rid(stk, ctx, opt).await? {
return Err(Error::IdMismatch {
value: id.to_string(),
});
@ -239,7 +238,7 @@ impl Iterator {
// Check if there is a data clause
if let Some(data) = stm.data() {
// Check if there is an id field specified
if let Some(id) = data.rid(stk, ctx, opt, txn).await? {
if let Some(id) = data.rid(stk, ctx, opt).await? {
return Err(Error::IdMismatch {
value: id.to_string(),
});
@ -282,7 +281,6 @@ impl Iterator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Log the statement
@ -291,9 +289,9 @@ impl Iterator {
let mut cancel_ctx = Context::new(ctx);
self.run = cancel_ctx.add_cancel();
// Process the query LIMIT clause
self.setup_limit(stk, &cancel_ctx, opt, txn, stm).await?;
self.setup_limit(stk, &cancel_ctx, opt, stm).await?;
// Process the query START clause
self.setup_start(stk, &cancel_ctx, opt, txn, stm).await?;
self.setup_start(stk, &cancel_ctx, opt, stm).await?;
// Prepare the results with possible optimisations on groups
self.results = self.results.prepare(
#[cfg(any(
@ -317,20 +315,20 @@ impl Iterator {
let is_last = matches!(s, IterationStage::Iterate(_));
cancel_ctx.set_iteration_stage(s);
if !is_last {
self.clone().iterate(stk, &cancel_ctx, opt, txn, stm).await?;
self.clone().iterate(stk, &cancel_ctx, opt, stm).await?;
};
}
}
self.iterate(stk, &cancel_ctx, opt, txn, stm).await?;
self.iterate(stk, &cancel_ctx, opt, stm).await?;
// Return any document errors
if let Some(e) = self.error.take() {
return Err(e);
}
// Process any SPLIT clause
self.output_split(stk, ctx, opt, txn, stm).await?;
self.output_split(stk, ctx, opt, stm).await?;
// Process any GROUP clause
if let Results::Groups(g) = &mut self.results {
self.results = Results::Memory(g.output(stk, ctx, opt, txn, stm).await?);
self.results = Results::Memory(g.output(stk, ctx, opt, stm).await?);
}
// Process any ORDER clause
@ -345,7 +343,7 @@ impl Iterator {
e.add_fetch(self.results.len());
} else {
// Process any FETCH clause
self.output_fetch(stk, ctx, opt, txn, stm).await?;
self.output_fetch(stk, ctx, opt, stm).await?;
}
}
@ -370,11 +368,10 @@ impl Iterator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
if let Some(v) = stm.limit() {
self.limit = Some(v.process(stk, ctx, opt, txn, None).await?);
self.limit = Some(v.process(stk, ctx, opt, None).await?);
}
Ok(())
}
@ -385,11 +382,10 @@ impl Iterator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
if let Some(v) = stm.start() {
self.start = Some(v.process(stk, ctx, opt, txn, None).await?);
self.start = Some(v.process(stk, ctx, opt, None).await?);
}
Ok(())
}
@ -400,7 +396,6 @@ impl Iterator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
if let Some(splits) = stm.split() {
@ -419,18 +414,18 @@ impl Iterator {
// Make a copy of object
let mut obj = obj.clone();
// Set the value at the path
obj.set(stk, ctx, opt, txn, split, val).await?;
obj.set(stk, ctx, opt, split, val).await?;
// Add the object to the results
self.results.push(stk, ctx, opt, txn, stm, obj).await?;
self.results.push(stk, ctx, opt, stm, obj).await?;
}
}
_ => {
// Make a copy of object
let mut obj = obj.clone();
// Set the value at the path
obj.set(stk, ctx, opt, txn, split, val).await?;
obj.set(stk, ctx, opt, split, val).await?;
// Add the object to the results
self.results.push(stk, ctx, opt, txn, stm, obj).await?;
self.results.push(stk, ctx, opt, stm, obj).await?;
}
}
}
@ -445,7 +440,6 @@ impl Iterator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
if let Some(fetchs) = stm.fetch() {
@ -454,7 +448,7 @@ impl Iterator {
// Loop over each result value
for obj in &mut values {
// Fetch the value at the path
stk.run(|stk| obj.fetch(stk, ctx, opt, txn, fetch)).await?;
stk.run(|stk| obj.fetch(stk, ctx, opt, fetch)).await?;
}
self.results = values.into();
}
@ -468,7 +462,6 @@ impl Iterator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
// Prevent deep recursion
@ -477,7 +470,7 @@ impl Iterator {
let mut distinct = SyncDistinct::new(ctx);
// Process all prepared values
for v in mem::take(&mut self.entries) {
v.iterate(stk, ctx, opt, txn, stm, self, distinct.as_mut()).await?;
v.iterate(stk, ctx, opt, stm, self, distinct.as_mut()).await?;
}
// Everything processed ok
Ok(())
@ -489,7 +482,6 @@ impl Iterator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
// Prevent deep recursion
@ -502,7 +494,7 @@ impl Iterator {
let mut distinct = SyncDistinct::new(ctx);
// Process all prepared values
for v in mem::take(&mut self.entries) {
v.iterate(stk, ctx, opt, txn, stm, self, distinct.as_mut()).await?;
v.iterate(stk, ctx, opt, stm, self, distinct.as_mut()).await?;
}
// Everything processed ok
Ok(())
@ -530,7 +522,7 @@ impl Iterator {
let mut stack = TreeStack::new();
stack
.enter(|stk| {
v.channel(stk, ctx, opt, txn, stm, chn_clone, distinct_clone)
v.channel(stk, ctx, opt, stm, chn_clone, distinct_clone)
})
.finish()
.await
@ -551,9 +543,7 @@ impl Iterator {
e.spawn(async move {
let mut stack = TreeStack::new();
stack
.enter(|stk| {
Document::compute(stk, ctx, opt, txn, stm, chn_clone, pro)
})
.enter(|stk| Document::compute(stk, ctx, opt, stm, chn_clone, pro))
.finish()
.await
})
@ -567,7 +557,7 @@ impl Iterator {
let aproc = async {
// Process all processed values
while let Ok(r) = vals.recv().await {
self.result(stk, ctx, opt, txn, stm, r).await;
self.result(stk, ctx, opt, stm, r).await;
}
// Shutdown the executor
let _ = end.send(()).await;
@ -590,14 +580,13 @@ impl Iterator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
pro: Processed,
) {
// Process the document
let res = stk.run(|stk| Document::process(stk, ctx, opt, txn, stm, pro)).await;
let res = stk.run(|stk| Document::process(stk, ctx, opt, stm, pro)).await;
// Process the result
self.result(stk, ctx, opt, txn, stm, res).await;
self.result(stk, ctx, opt, stm, res).await;
}
/// Accept a processed record result
@ -606,7 +595,6 @@ impl Iterator {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
res: Result<Value, Error>,
) {
@ -621,7 +609,7 @@ impl Iterator {
return;
}
Ok(v) => {
if let Err(e) = self.results.push(stk, ctx, opt, txn, stm, v).await {
if let Err(e) = self.results.push(stk, ctx, opt, stm, v).await {
self.error = Some(e);
self.run.cancel();
return;

View file

@ -1,4 +1,3 @@
use super::capabilities::Capabilities;
use crate::cnf::MAX_COMPUTATION_DEPTH;
use crate::dbs::Notification;
use crate::err::Error;
@ -47,8 +46,6 @@ pub struct Options {
pub projections: bool,
/// The channel over which we send notifications
pub sender: Option<Sender<Notification>>,
/// Datastore capabilities
pub capabilities: Arc<Capabilities>,
}
#[derive(Clone, Debug)]
@ -94,7 +91,6 @@ impl Options {
auth_enabled: true,
sender: None,
auth: Arc::new(Auth::default()),
capabilities: Arc::new(Capabilities::default()),
}
}
@ -119,7 +115,7 @@ impl Options {
/// instances when there is doubt.
pub fn with_required(
mut self,
node_id: uuid::Uuid,
node_id: Uuid,
ns: Option<Arc<str>>,
db: Option<Arc<str>>,
auth: Arc<Auth>,
@ -215,12 +211,6 @@ impl Options {
self
}
/// Create a new Options object with the given Capabilities
pub fn with_capabilities(mut self, capabilities: Arc<Capabilities>) -> Self {
self.capabilities = capabilities;
self
}
// --------------------------------------------------
/// Create a new Options object for a subquery
@ -228,7 +218,6 @@ impl Options {
Self {
sender: self.sender.clone(),
auth: self.auth.clone(),
capabilities: self.capabilities.clone(),
ns: self.ns.clone(),
db: self.db.clone(),
force: self.force.clone(),
@ -242,7 +231,6 @@ impl Options {
Self {
sender: self.sender.clone(),
auth: self.auth.clone(),
capabilities: self.capabilities.clone(),
ns: self.ns.clone(),
db: self.db.clone(),
force,
@ -255,7 +243,6 @@ impl Options {
Self {
sender: self.sender.clone(),
auth: self.auth.clone(),
capabilities: self.capabilities.clone(),
ns: self.ns.clone(),
db: self.db.clone(),
force: self.force.clone(),
@ -269,7 +256,6 @@ impl Options {
Self {
sender: self.sender.clone(),
auth: self.auth.clone(),
capabilities: self.capabilities.clone(),
ns: self.ns.clone(),
db: self.db.clone(),
force: self.force.clone(),
@ -283,7 +269,6 @@ impl Options {
Self {
sender: self.sender.clone(),
auth: self.auth.clone(),
capabilities: self.capabilities.clone(),
ns: self.ns.clone(),
db: self.db.clone(),
force: self.force.clone(),
@ -297,7 +282,6 @@ impl Options {
Self {
sender: self.sender.clone(),
auth: self.auth.clone(),
capabilities: self.capabilities.clone(),
ns: self.ns.clone(),
db: self.db.clone(),
force: self.force.clone(),
@ -310,7 +294,6 @@ impl Options {
pub fn new_with_sender(&self, sender: Sender<Notification>) -> Self {
Self {
auth: self.auth.clone(),
capabilities: self.capabilities.clone(),
ns: self.ns.clone(),
db: self.db.clone(),
force: self.force.clone(),
@ -340,7 +323,6 @@ impl Options {
Ok(Self {
sender: self.sender.clone(),
auth: self.auth.clone(),
capabilities: self.capabilities.clone(),
ns: self.ns.clone(),
db: self.db.clone(),
force: self.force.clone(),

View file

@ -3,7 +3,7 @@ use crate::ctx::Context;
#[cfg(not(target_arch = "wasm32"))]
use crate::dbs::distinct::AsyncDistinct;
use crate::dbs::distinct::SyncDistinct;
use crate::dbs::{Iterable, Iterator, Operable, Options, Processed, Statement, Transaction};
use crate::dbs::{Iterable, Iterator, Operable, Options, Processed, Statement};
use crate::err::Error;
use crate::idx::planner::iterators::{CollectorRecord, IteratorRef, ThingIterator};
use crate::idx::planner::IterationStage;
@ -19,38 +19,34 @@ use std::ops::Bound;
use std::vec;
impl Iterable {
#[allow(clippy::too_many_arguments)]
pub(crate) async fn iterate(
self,
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
ite: &mut Iterator,
dis: Option<&mut SyncDistinct>,
) -> Result<(), Error> {
if self.iteration_stage_check(ctx) {
Processor::Iterator(dis, ite).process_iterable(stk, ctx, opt, txn, stm, self).await
Processor::Iterator(dis, ite).process_iterable(stk, ctx, opt, stm, self).await
} else {
Ok(())
}
}
#[cfg(not(target_arch = "wasm32"))]
#[allow(clippy::too_many_arguments)]
pub(crate) async fn channel(
self,
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
chn: Sender<Processed>,
dis: Option<AsyncDistinct>,
) -> Result<(), Error> {
if self.iteration_stage_check(ctx) {
Processor::Channel(dis, chn).process_iterable(stk, ctx, opt, txn, stm, self).await
Processor::Channel(dis, chn).process_iterable(stk, ctx, opt, stm, self).await
} else {
Ok(())
}
@ -85,7 +81,6 @@ impl<'a> Processor<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
pro: Processed,
) -> Result<(), Error> {
@ -97,7 +92,7 @@ impl<'a> Processor<'a> {
false
};
if !is_processed {
ite.process(stk, ctx, opt, txn, stm, pro).await;
ite.process(stk, ctx, opt, stm, pro).await;
}
}
#[cfg(not(target_arch = "wasm32"))]
@ -120,15 +115,14 @@ impl<'a> Processor<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
iterable: Iterable,
) -> Result<(), Error> {
if ctx.is_ok() {
match iterable {
Iterable::Value(v) => self.process_value(stk, ctx, opt, txn, stm, v).await?,
Iterable::Thing(v) => self.process_thing(stk, ctx, opt, txn, stm, v).await?,
Iterable::Defer(v) => self.process_defer(stk, ctx, opt, txn, stm, v).await?,
Iterable::Value(v) => self.process_value(stk, ctx, opt, stm, v).await?,
Iterable::Thing(v) => self.process_thing(stk, ctx, opt, stm, v).await?,
Iterable::Defer(v) => self.process_defer(stk, ctx, opt, stm, v).await?,
Iterable::Table(v) => {
if let Some(qp) = ctx.get_query_planner() {
if let Some(exe) = qp.get_query_executor(&v.0) {
@ -136,13 +130,13 @@ impl<'a> Processor<'a> {
// Avoiding search in the hashmap of the query planner for each doc
let mut ctx = Context::new(ctx);
ctx.set_query_executor(exe.clone());
return self.process_table(stk, &ctx, opt, txn, stm, &v).await;
return self.process_table(stk, &ctx, opt, stm, &v).await;
}
}
self.process_table(stk, ctx, opt, txn, stm, &v).await?
self.process_table(stk, ctx, opt, stm, &v).await?
}
Iterable::Range(v) => self.process_range(stk, ctx, opt, txn, stm, v).await?,
Iterable::Edges(e) => self.process_edge(stk, ctx, opt, txn, stm, e).await?,
Iterable::Range(v) => self.process_range(stk, ctx, opt, stm, v).await?,
Iterable::Edges(e) => self.process_edge(stk, ctx, opt, stm, e).await?,
Iterable::Index(t, irf) => {
if let Some(qp) = ctx.get_query_planner() {
if let Some(exe) = qp.get_query_executor(&t.0) {
@ -150,16 +144,16 @@ impl<'a> Processor<'a> {
// Avoiding search in the hashmap of the query planner for each doc
let mut ctx = Context::new(ctx);
ctx.set_query_executor(exe.clone());
return self.process_index(stk, &ctx, opt, txn, stm, &t, irf).await;
return self.process_index(stk, &ctx, opt, stm, &t, irf).await;
}
}
self.process_index(stk, ctx, opt, txn, stm, &t, irf).await?
self.process_index(stk, ctx, opt, stm, &t, irf).await?
}
Iterable::Mergeable(v, o) => {
self.process_mergeable(stk, ctx, opt, txn, stm, v, o).await?
self.process_mergeable(stk, ctx, opt, stm, v, o).await?
}
Iterable::Relatable(f, v, w) => {
self.process_relatable(stk, ctx, opt, txn, stm, f, v, w).await?
self.process_relatable(stk, ctx, opt, stm, f, v, w).await?
}
}
}
@ -171,7 +165,6 @@ impl<'a> Processor<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
v: Value,
) -> Result<(), Error> {
@ -182,7 +175,7 @@ impl<'a> Processor<'a> {
val: Operable::Value(v),
};
// Process the document record
self.process(stk, ctx, opt, txn, stm, pro).await
self.process(stk, ctx, opt, stm, pro).await
}
async fn process_thing(
@ -190,15 +183,14 @@ impl<'a> Processor<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
v: Thing,
) -> Result<(), Error> {
// Check that the table exists
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
// Fetch the data from the store
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
let val = txn.clone().lock().await.get(key).await?;
let val = ctx.tx_lock().await.get(key).await?;
// Parse the data from the store
let val = Operable::Value(match val {
Some(v) => Value::from(v),
@ -210,7 +202,7 @@ impl<'a> Processor<'a> {
ir: None,
val,
};
self.process(stk, ctx, opt, txn, stm, pro).await?;
self.process(stk, ctx, opt, stm, pro).await?;
// Everything ok
Ok(())
}
@ -220,39 +212,36 @@ impl<'a> Processor<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
v: Thing,
) -> Result<(), Error> {
// Check that the table exists
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
// Process the document record
let pro = Processed {
rid: Some(v),
ir: None,
val: Operable::Value(Value::None),
};
self.process(stk, ctx, opt, txn, stm, pro).await?;
self.process(stk, ctx, opt, stm, pro).await?;
// Everything ok
Ok(())
}
#[allow(clippy::too_many_arguments)]
async fn process_mergeable(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
v: Thing,
o: Value,
) -> Result<(), Error> {
// Check that the table exists
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
// Fetch the data from the store
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
let val = txn.clone().lock().await.get(key).await?;
let val = ctx.tx_lock().await.get(key).await?;
// Parse the data from the store
let x = match val {
Some(v) => Value::from(v),
@ -266,7 +255,7 @@ impl<'a> Processor<'a> {
ir: None,
val,
};
self.process(stk, ctx, opt, txn, stm, pro).await?;
self.process(stk, ctx, opt, stm, pro).await?;
// Everything ok
Ok(())
}
@ -277,17 +266,16 @@ impl<'a> Processor<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
f: Thing,
v: Thing,
w: Thing,
) -> Result<(), Error> {
// Check that the table exists
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
// Fetch the data from the store
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
let val = txn.clone().lock().await.get(key).await?;
let val = ctx.tx_lock().await.get(key).await?;
// Parse the data from the store
let x = match val {
Some(v) => Value::from(v),
@ -301,7 +289,7 @@ impl<'a> Processor<'a> {
ir: None,
val,
};
self.process(stk, ctx, opt, txn, stm, pro).await?;
self.process(stk, ctx, opt, stm, pro).await?;
// Everything ok
Ok(())
}
@ -311,12 +299,11 @@ impl<'a> Processor<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
v: &Table,
) -> Result<(), Error> {
// Check that the table exists
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), v, opt.strict).await?;
ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), v, opt.strict).await?;
// Prepare the start and end keys
let beg = thing::prefix(opt.ns(), opt.db(), v);
let end = thing::suffix(opt.ns(), opt.db(), v);
@ -328,7 +315,7 @@ impl<'a> Processor<'a> {
break;
}
// Get the next batch of key-value entries
let res = txn.clone().lock().await.scan_paged(page, PROCESSOR_BATCH_SIZE).await?;
let res = ctx.tx_lock().await.scan_paged(page, PROCESSOR_BATCH_SIZE).await?;
next_page = res.next_page;
let res = res.values;
// If no results then break
@ -353,7 +340,7 @@ impl<'a> Processor<'a> {
ir: None,
val,
};
self.process(stk, ctx, opt, txn, stm, pro).await?;
self.process(stk, ctx, opt, stm, pro).await?;
}
continue;
}
@ -366,12 +353,11 @@ impl<'a> Processor<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
v: Range,
) -> Result<(), Error> {
// Check that the table exists
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
// Prepare the range start key
let beg = match &v.beg {
Bound::Unbounded => thing::prefix(opt.ns(), opt.db(), &v.tb),
@ -399,7 +385,7 @@ impl<'a> Processor<'a> {
if ctx.is_done() {
break;
}
let res = txn.clone().lock().await.scan_paged(page, PROCESSOR_BATCH_SIZE).await?;
let res = ctx.tx_lock().await.scan_paged(page, PROCESSOR_BATCH_SIZE).await?;
next_page = res.next_page;
// Get the next batch of key-value entries
let res = res.values;
@ -425,7 +411,7 @@ impl<'a> Processor<'a> {
ir: None,
val,
};
self.process(stk, ctx, opt, txn, stm, pro).await?;
self.process(stk, ctx, opt, stm, pro).await?;
}
continue;
}
@ -438,7 +424,6 @@ impl<'a> Processor<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
e: Edges,
) -> Result<(), Error> {
@ -520,7 +505,7 @@ impl<'a> Processor<'a> {
break;
}
// Get the next batch key-value entries
let res = txn.lock().await.scan_paged(page, PROCESSOR_BATCH_SIZE).await?;
let res = ctx.tx_lock().await.scan_paged(page, PROCESSOR_BATCH_SIZE).await?;
next_page = res.next_page;
let res = res.values;
// If there are key-value entries then fetch them
@ -537,7 +522,7 @@ impl<'a> Processor<'a> {
let gra: graph::Graph = graph::Graph::decode(&k)?;
// Fetch the data from the store
let key = thing::new(opt.ns(), opt.db(), gra.ft, &gra.fk);
let val = txn.lock().await.get(key).await?;
let val = ctx.tx_lock().await.get(key).await?;
let rid = Thing::from((gra.ft, gra.fk));
// Parse the data from the store
let val = Operable::Value(match val {
@ -550,7 +535,7 @@ impl<'a> Processor<'a> {
ir: None,
val,
};
self.process(stk, ctx, opt, txn, stm, pro).await?;
self.process(stk, ctx, opt, stm, pro).await?;
}
continue;
}
@ -559,23 +544,21 @@ impl<'a> Processor<'a> {
Ok(())
}
#[allow(clippy::too_many_arguments)]
async fn process_index(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
table: &Table,
irf: IteratorRef,
) -> Result<(), Error> {
// Check that the table exists
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &table.0, opt.strict).await?;
ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &table.0, opt.strict).await?;
if let Some(exe) = ctx.get_query_executor() {
if let Some(mut iterator) = exe.new_iterator(opt, irf).await? {
// Get the first batch
let mut to_process = Self::next_batch(ctx, opt, txn, &mut iterator).await?;
let mut to_process = Self::next_batch(ctx, opt, &mut iterator).await?;
while !to_process.is_empty() {
// Check if the context is finished
@ -585,10 +568,10 @@ impl<'a> Processor<'a> {
// Process the records
// TODO: par_iter
for pro in to_process {
self.process(stk, ctx, opt, txn, stm, pro).await?;
self.process(stk, ctx, opt, stm, pro).await?;
}
// Get the next batch
to_process = Self::next_batch(ctx, opt, txn, &mut iterator).await?;
to_process = Self::next_batch(ctx, opt, &mut iterator).await?;
}
// Everything ok
return Ok(());
@ -606,10 +589,9 @@ impl<'a> Processor<'a> {
async fn next_batch(
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
iterator: &mut ThingIterator,
) -> Result<Vec<Processed>, Error> {
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
let records: Vec<CollectorRecord> =
iterator.next_batch(ctx, &mut tx, PROCESSOR_BATCH_SIZE).await?;
let mut to_process = Vec::with_capacity(records.len());

View file

@ -12,7 +12,7 @@ use crate::dbs::plan::Explanation;
))]
use crate::dbs::store::file_store::FileCollector;
use crate::dbs::store::MemoryCollector;
use crate::dbs::{Options, Statement, Transaction};
use crate::dbs::{Options, Statement};
use crate::err::Error;
use crate::sql::{Orders, Value};
use reblessive::tree::Stk;
@ -73,7 +73,6 @@ impl Results {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
val: Value,
) -> Result<(), Error> {
@ -95,7 +94,7 @@ impl Results {
e.push(val)?;
}
Self::Groups(g) => {
g.push(stk, ctx, opt, txn, stm, val).await?;
g.push(stk, ctx, opt, stm, val).await?;
}
}
Ok(())

View file

@ -1,14 +1,14 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::iam::Auth;
use crate::iam::Role;
use crate::kvs::{Datastore, LockType::*, TransactionType::*};
use std::sync::Arc;
pub async fn mock<'a>() -> (Context<'a>, Options, Transaction) {
let ctx = Context::default();
pub async fn mock<'a>() -> (Context<'a>, Options) {
let opt = Options::default().with_auth(Arc::new(Auth::for_root(Role::Owner)));
let kvs = Datastore::new("memory").await.unwrap();
let txn = kvs.transaction(Write, Optimistic).await.unwrap().rollback_and_ignore().enclose();
(ctx, opt, txn)
let ctx = Context::default().set_transaction(txn);
(ctx, opt)
}

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::permission::Permission;
@ -12,7 +12,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
// Check if this record exists
@ -20,7 +19,7 @@ impl<'a> Document<'a> {
// Should we run permissions checks?
if opt.check_perms(stm.into()) {
// Get the table
let tb = self.tb(opt, txn).await?;
let tb = self.tb(ctx, opt).await?;
// Get the permission clause
let perms = if stm.is_delete() {
&tb.permissions.delete
@ -44,7 +43,6 @@ impl<'a> Document<'a> {
stk,
ctx,
opt,
txn,
Some(match stm.is_delete() {
true => &self.initial,
false => &self.current,

View file

@ -1,7 +1,7 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::Workable;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::data::Data;
@ -15,7 +15,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
// Get the record id
@ -26,57 +25,39 @@ impl<'a> Document<'a> {
if let Some(v) = stm.data() {
match v {
Data::PatchExpression(data) => {
let data = data.compute(stk, ctx, opt, txn, Some(&self.current)).await?;
let data = data.compute(stk, ctx, opt, Some(&self.current)).await?;
self.current.doc.to_mut().patch(data)?
}
Data::MergeExpression(data) => {
let data = data.compute(stk, ctx, opt, txn, Some(&self.current)).await?;
let data = data.compute(stk, ctx, opt, Some(&self.current)).await?;
self.current.doc.to_mut().merge(data)?
}
Data::ReplaceExpression(data) => {
let data = data.compute(stk, ctx, opt, txn, Some(&self.current)).await?;
let data = data.compute(stk, ctx, opt, Some(&self.current)).await?;
self.current.doc.to_mut().replace(data)?
}
Data::ContentExpression(data) => {
let data = data.compute(stk, ctx, opt, txn, Some(&self.current)).await?;
let data = data.compute(stk, ctx, opt, Some(&self.current)).await?;
self.current.doc.to_mut().replace(data)?
}
Data::SetExpression(x) => {
for x in x.iter() {
let v = x.2.compute(stk, ctx, opt, txn, Some(&self.current)).await?;
let v = x.2.compute(stk, ctx, opt, Some(&self.current)).await?;
match x.1 {
Operator::Equal => match v {
Value::None => {
self.current.doc.to_mut().del(stk, ctx, opt, txn, &x.0).await?
}
_ => {
self.current
.doc
.to_mut()
.set(stk, ctx, opt, txn, &x.0, v)
.await?
self.current.doc.to_mut().del(stk, ctx, opt, &x.0).await?
}
_ => self.current.doc.to_mut().set(stk, ctx, opt, &x.0, v).await?,
},
Operator::Inc => {
self.current
.doc
.to_mut()
.increment(stk, ctx, opt, txn, &x.0, v)
.await?
self.current.doc.to_mut().increment(stk, ctx, opt, &x.0, v).await?
}
Operator::Dec => {
self.current
.doc
.to_mut()
.decrement(stk, ctx, opt, txn, &x.0, v)
.await?
self.current.doc.to_mut().decrement(stk, ctx, opt, &x.0, v).await?
}
Operator::Ext => {
self.current
.doc
.to_mut()
.extend(stk, ctx, opt, txn, &x.0, v)
.await?
self.current.doc.to_mut().extend(stk, ctx, opt, &x.0, v).await?
}
_ => unreachable!(),
}
@ -84,7 +65,7 @@ impl<'a> Document<'a> {
}
Data::UnsetExpression(i) => {
for i in i.iter() {
self.current.doc.to_mut().del(stk, ctx, opt, txn, i).await?
self.current.doc.to_mut().del(stk, ctx, opt, i).await?
}
}
Data::UpdateExpression(x) => {
@ -96,40 +77,22 @@ impl<'a> Document<'a> {
}
// Process ON DUPLICATE KEY clause
for x in x.iter() {
let v = x.2.compute(stk, &ctx, opt, txn, Some(&self.current)).await?;
let v = x.2.compute(stk, &ctx, opt, Some(&self.current)).await?;
match x.1 {
Operator::Equal => match v {
Value::None => {
self.current.doc.to_mut().del(stk, &ctx, opt, txn, &x.0).await?
}
_ => {
self.current
.doc
.to_mut()
.set(stk, &ctx, opt, txn, &x.0, v)
.await?
self.current.doc.to_mut().del(stk, &ctx, opt, &x.0).await?
}
_ => self.current.doc.to_mut().set(stk, &ctx, opt, &x.0, v).await?,
},
Operator::Inc => {
self.current
.doc
.to_mut()
.increment(stk, &ctx, opt, txn, &x.0, v)
.await?
self.current.doc.to_mut().increment(stk, &ctx, opt, &x.0, v).await?
}
Operator::Dec => {
self.current
.doc
.to_mut()
.decrement(stk, &ctx, opt, txn, &x.0, v)
.await?
self.current.doc.to_mut().decrement(stk, &ctx, opt, &x.0, v).await?
}
Operator::Ext => {
self.current
.doc
.to_mut()
.extend(stk, &ctx, opt, txn, &x.0, v)
.await?
self.current.doc.to_mut().extend(stk, &ctx, opt, &x.0, v).await?
}
_ => unreachable!(),
}

View file

@ -1,16 +1,14 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::Transaction;
use crate::doc::Document;
use crate::err::Error;
impl<'a> Document<'a> {
pub async fn changefeeds(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Check if changed
@ -18,11 +16,9 @@ impl<'a> Document<'a> {
return Ok(());
}
//
let tb = self.tb(opt, txn).await?;
// Clone transaction
let run = txn.clone();
let tb = self.tb(ctx, opt).await?;
// Claim transaction
let mut run = run.lock().await;
let mut run = ctx.tx_lock().await;
// Get the database and the table for the record
let db = run.add_and_cache_db(opt.ns(), opt.db(), opt.strict).await?;
// Check if changefeeds are enabled

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::{CursorDoc, Document};
use crate::err::Error;
use crate::sql::Cond;
@ -12,24 +12,22 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
Self::check_cond(stk, ctx, opt, txn, stm.conds(), &self.current).await
Self::check_cond(stk, ctx, opt, stm.conds(), &self.current).await
}
pub(crate) async fn check_cond(
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
cond: Option<&Cond>,
doc: &CursorDoc<'_>,
) -> Result<(), Error> {
// Check where condition
if let Some(cond) = cond {
// Check if the expression is truthy
if !cond.compute(stk, ctx, opt, txn, Some(doc)).await?.is_truthy() {
if !cond.compute(stk, ctx, opt, Some(doc)).await?.is_truthy() {
// Ignore this document
return Err(Error::Ignore);
}

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::idiom::Idiom;
@ -12,17 +12,16 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Get the table
let tb = self.tb(opt, txn).await?;
let tb = self.tb(ctx, opt).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() {
for fd in self.fd(ctx, opt).await?.iter() {
// Is this a schemaless field?
match fd.flex {
false => {
@ -47,7 +46,7 @@ impl<'a> Document<'a> {
fd if fd.is_in() => continue,
fd if fd.is_out() => continue,
fd if fd.is_meta() => continue,
fd => self.current.doc.to_mut().del(stk, ctx, opt, txn, fd).await?,
fd => self.current.doc.to_mut().del(stk, ctx, opt, fd).await?,
}
}
}

View file

@ -1,7 +1,7 @@
use crate::ctx::Context;
use crate::dbs::Operable;
use crate::dbs::Statement;
use crate::dbs::Workable;
use crate::dbs::{Operable, Transaction};
use crate::dbs::{Options, Processed};
use crate::doc::Document;
use crate::err::Error;
@ -15,7 +15,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
chn: Sender<Result<Value, Error>>,
mut pro: Processed,
@ -36,12 +35,12 @@ impl<'a> Document<'a> {
let mut doc = Document::new(pro.rid.as_ref(), pro.ir.as_ref(), &ins.0, ins.1);
// Process the statement
let res = match stm {
Statement::Select(_) => doc.select(stk, ctx, opt, txn, stm).await,
Statement::Create(_) => doc.create(stk, ctx, opt, txn, stm).await,
Statement::Update(_) => doc.update(stk, ctx, opt, txn, stm).await,
Statement::Relate(_) => doc.relate(stk, ctx, opt, txn, stm).await,
Statement::Delete(_) => doc.delete(stk, ctx, opt, txn, stm).await,
Statement::Insert(_) => doc.insert(stk, ctx, opt, txn, stm).await,
Statement::Select(_) => doc.select(stk, ctx, opt, stm).await,
Statement::Create(_) => doc.create(stk, ctx, opt, stm).await,
Statement::Update(_) => doc.update(stk, ctx, opt, stm).await,
Statement::Relate(_) => doc.relate(stk, ctx, opt, stm).await,
Statement::Delete(_) => doc.delete(stk, ctx, opt, stm).await,
Statement::Insert(_) => doc.insert(stk, ctx, opt, stm).await,
_ => unreachable!(),
};
// Check the result
@ -52,7 +51,7 @@ impl<'a> Document<'a> {
Err(Error::RetryWithId(v)) => {
// Fetch the data from the store
let key = crate::key::thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
let val = txn.clone().lock().await.get(key).await?;
let val = ctx.tx_lock().await.get(key).await?;
// Parse the data from the store
let val = match val {
Some(v) => Value::from(v),

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::value::Value;
@ -12,34 +12,33 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check if table has corrent relation status
self.relation(ctx, opt, txn, stm).await?;
self.relation(ctx, opt, stm).await?;
// Alter record data
self.alter(stk, ctx, opt, txn, stm).await?;
self.alter(stk, ctx, opt, stm).await?;
// Merge fields data
self.field(stk, ctx, opt, txn, stm).await?;
self.field(stk, ctx, opt, stm).await?;
// Reset fields data
self.reset(ctx, opt, txn, stm).await?;
self.reset(ctx, opt, stm).await?;
// Clean fields data
self.clean(stk, ctx, opt, txn, stm).await?;
self.clean(stk, ctx, opt, stm).await?;
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Store record data
self.store(ctx, opt, txn, stm).await?;
self.store(ctx, opt, stm).await?;
// Store index data
self.index(stk, ctx, opt, txn, stm).await?;
self.index(stk, ctx, opt, stm).await?;
// Run table queries
self.table(stk, ctx, opt, txn, stm).await?;
self.table(stk, ctx, opt, stm).await?;
// Run lives queries
self.lives(stk, ctx, opt, txn, stm).await?;
self.lives(stk, ctx, opt, stm).await?;
// Run change feeds queries
self.changefeeds(ctx, opt, txn, stm).await?;
self.changefeeds(ctx, opt, stm).await?;
// Run event queries
self.event(stk, ctx, opt, txn, stm).await?;
self.event(stk, ctx, opt, stm).await?;
// Yield document
self.pluck(stk, ctx, opt, txn, stm).await
self.pluck(stk, ctx, opt, stm).await
}
}

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::value::Value;
@ -12,28 +12,27 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check where clause
self.check(stk, ctx, opt, txn, stm).await?;
self.check(stk, ctx, opt, stm).await?;
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Erase document
self.erase(ctx, opt, stm).await?;
// Purge index data
self.index(stk, ctx, opt, txn, stm).await?;
self.index(stk, ctx, opt, stm).await?;
// Purge record data
self.purge(stk, ctx, opt, txn, stm).await?;
self.purge(stk, ctx, opt, stm).await?;
// Run table queries
self.table(stk, ctx, opt, txn, stm).await?;
self.table(stk, ctx, opt, stm).await?;
// Run lives queries
self.lives(stk, ctx, opt, txn, stm).await?;
self.lives(stk, ctx, opt, stm).await?;
// Run change feeds queries
self.changefeeds(ctx, opt, txn, stm).await?;
self.changefeeds(ctx, opt, stm).await?;
// Run event queries
self.event(stk, ctx, opt, txn, stm).await?;
self.event(stk, ctx, opt, stm).await?;
// Yield document
self.pluck(stk, ctx, opt, txn, stm).await
self.pluck(stk, ctx, opt, stm).await
}
}

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Transaction;
use crate::dbs::Workable;
use crate::err::Error;
use crate::iam::Action;
@ -144,13 +144,11 @@ impl<'a> Document<'a> {
/// Get the table for this document
pub async fn tb(
&self,
ctx: &Context<'a>,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<DefineTableStatement>, Error> {
// Clone transaction
let run = txn.clone();
// Claim transaction
let mut run = run.lock().await;
let mut run = ctx.tx_lock().await;
// Get the record id
let rid = self.id.as_ref().unwrap();
// Get the table definition
@ -177,56 +175,56 @@ impl<'a> Document<'a> {
/// Get the foreign tables for this document
pub async fn ft(
&self,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<[DefineTableStatement]>, Error> {
// Get the record id
let id = self.id.as_ref().unwrap();
// Get the table definitions
txn.clone().lock().await.all_tb_views(opt.ns(), opt.db(), &id.tb).await
ctx.tx_lock().await.all_tb_views(opt.ns(), opt.db(), &id.tb).await
}
/// Get the events for this document
pub async fn ev(
&self,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<[DefineEventStatement]>, Error> {
// Get the record id
let id = self.id.as_ref().unwrap();
// Get the event definitions
txn.clone().lock().await.all_tb_events(opt.ns(), opt.db(), &id.tb).await
ctx.tx_lock().await.all_tb_events(opt.ns(), opt.db(), &id.tb).await
}
/// Get the fields for this document
pub async fn fd(
&self,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<[DefineFieldStatement]>, Error> {
// Get the record id
let id = self.id.as_ref().unwrap();
// Get the field definitions
txn.clone().lock().await.all_tb_fields(opt.ns(), opt.db(), &id.tb).await
ctx.tx_lock().await.all_tb_fields(opt.ns(), opt.db(), &id.tb).await
}
/// Get the indexes for this document
pub async fn ix(
&self,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<[DefineIndexStatement]>, Error> {
// Get the record id
let id = self.id.as_ref().unwrap();
// Get the index definitions
txn.clone().lock().await.all_tb_indexes(opt.ns(), opt.db(), &id.tb).await
ctx.tx_lock().await.all_tb_indexes(opt.ns(), opt.db(), &id.tb).await
}
// Get the lives for this document
pub async fn lv(
&self,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<[LiveStatement]>, Error> {
// Get the record id
let id = self.id.as_ref().unwrap();
// Get the table definition
txn.clone().lock().await.all_tb_lives(opt.ns(), opt.db(), &id.tb).await
ctx.tx_lock().await.all_tb_lives(opt.ns(), opt.db(), &id.tb).await
}
}

View file

@ -1,7 +1,7 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::Workable;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::paths::EDGE;
@ -13,17 +13,16 @@ use crate::sql::Dir;
impl<'a> Document<'a> {
pub async fn edges(
&mut self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Check if the table is a view
if self.tb(opt, txn).await?.drop {
if self.tb(ctx, opt).await?.drop {
return Ok(());
}
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Get the record id
let rid = self.id.as_ref().unwrap();
// Store the record edges

View file

@ -1,7 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::Transaction;
use crate::doc::Document;
use crate::err::Error;
@ -10,7 +9,6 @@ impl<'a> Document<'a> {
&self,
_ctx: &Context<'_>,
_opt: &Options,
_txn: &Transaction,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Check if this record exists

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::value::Value;
@ -13,7 +13,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
// Check import
@ -27,7 +26,7 @@ impl<'a> Document<'a> {
// Don't run permissions
let opt = &opt.new_with_perms(false);
// Loop through all event statements
for ev in self.ev(opt, txn).await?.iter() {
for ev in self.ev(ctx, opt).await?.iter() {
// Get the event action
let met = if stm.is_delete() {
Value::from("DELETE")
@ -48,11 +47,11 @@ impl<'a> Document<'a> {
ctx.add_value("after", self.current.doc.deref());
ctx.add_value("before", self.initial.doc.deref());
// Process conditional clause
let val = ev.when.compute(stk, &ctx, opt, txn, Some(doc)).await?;
let val = ev.when.compute(stk, &ctx, opt, Some(doc)).await?;
// Execute event if value is truthy
if val.is_truthy() {
for v in ev.then.iter() {
v.compute(stk, &ctx, opt, txn, Some(doc)).await?;
v.compute(stk, &ctx, opt, Some(doc)).await?;
}
}
}

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::iam::Action;
@ -14,7 +14,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Check import
@ -26,7 +25,7 @@ impl<'a> Document<'a> {
// Get the user applied input
let inp = self.initial.doc.changed(self.current.doc.as_ref());
// Loop through all field statements
for fd in self.fd(opt, txn).await?.iter() {
for fd in self.fd(ctx, opt).await?.iter() {
// Loop over each field in document
for (k, mut val) in self.current.doc.walk(&fd.name).into_iter() {
// Get the initial value
@ -58,7 +57,7 @@ impl<'a> Document<'a> {
ctx.add_value("after", &val);
ctx.add_value("before", &old);
// Process the VALUE clause
val = expr.compute(stk, &ctx, opt, txn, Some(&self.current)).await?;
val = expr.compute(stk, &ctx, opt, Some(&self.current)).await?;
}
}
// Check for a TYPE clause
@ -89,7 +88,7 @@ impl<'a> Document<'a> {
ctx.add_value("after", &val);
ctx.add_value("before", &old);
// Process the VALUE clause
val = expr.compute(stk, &ctx, opt, txn, Some(&self.current)).await?;
val = expr.compute(stk, &ctx, opt, Some(&self.current)).await?;
}
}
// Check for a TYPE clause
@ -118,7 +117,7 @@ impl<'a> Document<'a> {
ctx.add_value("after", &val);
ctx.add_value("before", &old);
// Process the ASSERT clause
if !expr.compute(stk, &ctx, opt, txn, Some(&self.current)).await?.is_truthy() {
if !expr.compute(stk, &ctx, opt, Some(&self.current)).await?.is_truthy() {
return Err(Error::FieldValue {
thing: rid.to_string(),
field: fd.name.clone(),
@ -159,11 +158,7 @@ impl<'a> Document<'a> {
ctx.add_value("after", &val);
ctx.add_value("before", &old);
// Process the PERMISSION clause
if !e
.compute(stk, &ctx, opt, txn, Some(&self.current))
.await?
.is_truthy()
{
if !e.compute(stk, &ctx, opt, Some(&self.current)).await?.is_truthy() {
val = old
}
}
@ -171,8 +166,8 @@ impl<'a> Document<'a> {
}
// Set the value of the field
match val {
Value::None => self.current.doc.to_mut().del(stk, ctx, opt, txn, &k).await?,
_ => self.current.doc.to_mut().set(stk, ctx, opt, txn, &k, val).await?,
Value::None => self.current.doc.to_mut().del(stk, ctx, opt, &k).await?,
_ => self.current.doc.to_mut().set(stk, ctx, opt, &k, val).await?,
};
}
}

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::{Force, Statement};
use crate::dbs::{Options, Transaction};
use crate::doc::{CursorDoc, Document};
use crate::err::Error;
use crate::idx::ft::FtIndex;
@ -20,7 +20,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Was this force targeted at a specific index?
@ -32,12 +31,12 @@ impl<'a> Document<'a> {
{
ix.clone()
}
Force::All => self.ix(opt, txn).await?,
_ if self.changed() => self.ix(opt, txn).await?,
Force::All => self.ix(ctx, opt).await?,
_ if self.changed() => self.ix(ctx, opt).await?,
_ => return Ok(()),
};
// Check if the table is a view
if self.tb(opt, txn).await?.drop {
if self.tb(ctx, opt).await?.drop {
return Ok(());
}
// Get the record id
@ -45,10 +44,10 @@ impl<'a> Document<'a> {
// Loop through all index statements
for ix in ixs.iter() {
// Calculate old values
let o = build_opt_values(stk, ctx, opt, txn, ix, &self.initial).await?;
let o = build_opt_values(stk, ctx, opt, ix, &self.initial).await?;
// Calculate new values
let n = build_opt_values(stk, ctx, opt, txn, ix, &self.current).await?;
let n = build_opt_values(stk, ctx, opt, ix, &self.current).await?;
// Update the index entries
if targeted_force || o != n {
@ -57,10 +56,10 @@ impl<'a> Document<'a> {
// Index operation dispatching
match &ix.index {
Index::Uniq => ic.index_unique(txn).await?,
Index::Idx => ic.index_non_unique(txn).await?,
Index::Search(p) => ic.index_full_text(stk, ctx, txn, p).await?,
Index::MTree(p) => ic.index_mtree(stk, ctx, txn, p).await?,
Index::Uniq => ic.index_unique(ctx).await?,
Index::Idx => ic.index_non_unique(ctx).await?,
Index::Search(p) => ic.index_full_text(stk, ctx, p).await?,
Index::MTree(p) => ic.index_mtree(stk, ctx, p).await?,
Index::Hnsw(p) => ic.index_hnsw(ctx, p).await?,
};
}
@ -78,7 +77,6 @@ async fn build_opt_values(
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
ix: &DefineIndexStatement,
doc: &CursorDoc<'_>,
) -> Result<Option<Vec<Value>>, Error> {
@ -87,7 +85,7 @@ async fn build_opt_values(
}
let mut o = Vec::with_capacity(ix.cols.len());
for i in ix.cols.iter() {
let v = i.compute(stk, ctx, opt, txn, Some(doc)).await?;
let v = i.compute(stk, ctx, opt, Some(doc)).await?;
o.push(v);
}
Ok(Some(o))
@ -281,8 +279,8 @@ impl<'a> IndexOperation<'a> {
)
}
async fn index_unique(&mut self, txn: &Transaction) -> Result<(), Error> {
let mut run = txn.lock().await;
async fn index_unique(&mut self, ctx: &Context<'_>) -> Result<(), Error> {
let mut run = ctx.tx_lock().await;
// Delete the old index data
if let Some(o) = self.o.take() {
let i = Indexable::new(o, self.ix);
@ -313,8 +311,8 @@ impl<'a> IndexOperation<'a> {
Ok(())
}
async fn index_non_unique(&mut self, txn: &Transaction) -> Result<(), Error> {
let mut run = txn.lock().await;
async fn index_non_unique(&mut self, ctx: &Context<'_>) -> Result<(), Error> {
let mut run = ctx.tx_lock().await;
// Delete the old index data
if let Some(o) = self.o.take() {
let i = Indexable::new(o, self.ix);
@ -358,38 +356,27 @@ impl<'a> IndexOperation<'a> {
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
txn: &Transaction,
p: &SearchParams,
) -> Result<(), Error> {
let ikb = IndexKeyBase::new(self.opt, self.ix);
let mut ft = FtIndex::new(
ctx.get_index_stores(),
self.opt,
txn,
&p.az,
ikb,
p,
TransactionType::Write,
)
.await?;
let mut ft = FtIndex::new(ctx, self.opt, &p.az, ikb, p, TransactionType::Write).await?;
if let Some(n) = self.n.take() {
ft.index_document(stk, ctx, self.opt, txn, self.rid, n).await?;
ft.index_document(stk, ctx, self.opt, self.rid, n).await?;
} else {
ft.remove_document(txn, self.rid).await?;
ft.remove_document(ctx, self.rid).await?;
}
ft.finish(txn).await
ft.finish(ctx).await
}
async fn index_mtree(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
txn: &Transaction,
p: &MTreeParams,
) -> Result<(), Error> {
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
let ikb = IndexKeyBase::new(self.opt, self.ix);
let mut mt =
MTreeIndex::new(ctx.get_index_stores(), &mut tx, ikb, p, TransactionType::Write)

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::value::Value;
@ -12,7 +12,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check whether current record exists
@ -20,13 +19,13 @@ impl<'a> Document<'a> {
// We attempted to INSERT a document with an ID,
// and this ID already exists in the database,
// so we need to update the record instead.
true => self.insert_update(stk, ctx, opt, txn, stm).await,
true => self.insert_update(stk, ctx, opt, stm).await,
// We attempted to INSERT a document with an ID,
// which does not exist in the database, or we
// are creating a new record with a new ID.
false => {
// First of all let's try to create the record
match self.insert_create(stk, ctx, opt, txn, stm).await {
match self.insert_create(stk, ctx, opt, stm).await {
// We received an index exists error, so we
// ignore the error, and attempt to update the
// record using the ON DUPLICATE KEY clause
@ -50,35 +49,34 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check if table has correct relation status
self.relation(ctx, opt, txn, stm).await?;
self.relation(ctx, opt, stm).await?;
// Merge record data
self.merge(stk, ctx, opt, txn, stm).await?;
self.merge(stk, ctx, opt, stm).await?;
// Merge fields data
self.field(stk, ctx, opt, txn, stm).await?;
self.field(stk, ctx, opt, stm).await?;
// Reset fields data
self.reset(ctx, opt, txn, stm).await?;
self.reset(ctx, opt, stm).await?;
// Clean fields data
self.clean(stk, ctx, opt, txn, stm).await?;
self.clean(stk, ctx, opt, stm).await?;
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Store index data
self.index(stk, ctx, opt, txn, stm).await?;
self.index(stk, ctx, opt, stm).await?;
// Store record data
self.store(ctx, opt, txn, stm).await?;
self.store(ctx, opt, stm).await?;
// Run table queries
self.table(stk, ctx, opt, txn, stm).await?;
self.table(stk, ctx, opt, stm).await?;
// Run lives queries
self.lives(stk, ctx, opt, txn, stm).await?;
self.lives(stk, ctx, opt, stm).await?;
// Run change feeds queries
self.changefeeds(ctx, opt, txn, stm).await?;
self.changefeeds(ctx, opt, stm).await?;
// Run event queries
self.event(stk, ctx, opt, txn, stm).await?;
self.event(stk, ctx, opt, stm).await?;
// Yield document
self.pluck(stk, ctx, opt, txn, stm).await
self.pluck(stk, ctx, opt, stm).await
}
// Attempt to run an UPDATE clause
async fn insert_update(
@ -86,34 +84,33 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Alter record data
self.alter(stk, ctx, opt, txn, stm).await?;
self.alter(stk, ctx, opt, stm).await?;
// Merge fields data
self.field(stk, ctx, opt, txn, stm).await?;
self.field(stk, ctx, opt, stm).await?;
// Reset fields data
self.reset(ctx, opt, txn, stm).await?;
self.reset(ctx, opt, stm).await?;
// Clean fields data
self.clean(stk, ctx, opt, txn, stm).await?;
self.clean(stk, ctx, opt, stm).await?;
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Store index data
self.index(stk, ctx, opt, txn, stm).await?;
self.index(stk, ctx, opt, stm).await?;
// Store record data
self.store(ctx, opt, txn, stm).await?;
self.store(ctx, opt, stm).await?;
// Run table queries
self.table(stk, ctx, opt, txn, stm).await?;
self.table(stk, ctx, opt, stm).await?;
// Run lives queries
self.lives(stk, ctx, opt, txn, stm).await?;
self.lives(stk, ctx, opt, stm).await?;
// Run change feeds queries
self.changefeeds(ctx, opt, txn, stm).await?;
self.changefeeds(ctx, opt, stm).await?;
// Run event queries
self.event(stk, ctx, opt, txn, stm).await?;
self.event(stk, ctx, opt, stm).await?;
// Yield document
self.pluck(stk, ctx, opt, txn, stm).await
self.pluck(stk, ctx, opt, stm).await
}
}

View file

@ -1,8 +1,8 @@
use crate::ctx::Context;
use crate::dbs::Action;
use crate::dbs::Notification;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Action, Transaction};
use crate::doc::CursorDoc;
use crate::doc::Document;
use crate::err::Error;
@ -24,9 +24,8 @@ impl<'a> Document<'a> {
pub async fn lives(
&self,
stk: &mut Stk,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
// Check if changed
@ -41,10 +40,9 @@ impl<'a> Document<'a> {
// Check if we can send notifications
if let Some(chn) = &opt.sender {
// Loop through all index statements
let lq_stms = self.lv(opt, txn).await?;
let lq_stms = self.lv(ctx, opt).await?;
let borrows = lq_stms.iter().collect::<Vec<_>>();
self.check_lqs_and_send_notifications(stk, opt, stm, txn, borrows.as_slice(), chn)
.await?;
self.check_lqs_and_send_notifications(stk, opt, stm, borrows.as_slice(), chn).await?;
}
// Carry on
Ok(())
@ -56,14 +54,13 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
doc: &CursorDoc<'_>,
) -> Result<(), Error> {
// Check where condition
if let Some(cond) = stm.conds() {
// Check if the expression is truthy
if !cond.compute(stk, ctx, opt, txn, Some(doc)).await?.is_truthy() {
if !cond.compute(stk, ctx, opt, Some(doc)).await?.is_truthy() {
// Ignore this document
return Err(Error::Ignore);
}
@ -78,14 +75,13 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
doc: &CursorDoc<'_>,
) -> Result<(), Error> {
// Should we run permissions checks?
if opt.check_perms(stm.into()) {
// Get the table
let tb = self.tb(opt, txn).await?;
let tb = self.tb(ctx, opt).await?;
// Process the table permissions
match &tb.permissions.select {
Permission::None => return Err(Error::Ignore),
@ -94,7 +90,7 @@ impl<'a> Document<'a> {
// Disable permissions
let opt = &opt.new_with_perms(false);
// Process the PERMISSION clause
if !e.compute(stk, ctx, opt, txn, Some(doc)).await?.is_truthy() {
if !e.compute(stk, ctx, opt, Some(doc)).await?.is_truthy() {
return Err(Error::Ignore);
}
}
@ -110,7 +106,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
opt: &Options,
stm: &Statement<'_>,
txn: &Transaction,
live_statements: &[&LiveStatement],
sender: &Sender<Notification>,
) -> Result<(), Error> {
@ -180,7 +175,7 @@ impl<'a> Document<'a> {
// First of all, let's check to see if the WHERE
// clause of the LIVE query is matched by this
// document. If it is then we can continue.
match self.lq_check(stk, &lqctx, &lqopt, txn, &lq, doc).await {
match self.lq_check(stk, &lqctx, &lqopt, &lq, doc).await {
Err(Error::Ignore) => {
trace!("live query did not match the where clause, skipping");
continue;
@ -192,7 +187,7 @@ impl<'a> Document<'a> {
// clause for this table allows this document to
// be viewed by the user who created this LIVE
// query. If it does, then we can continue.
match self.lq_allow(stk, &lqctx, &lqopt, txn, &lq, doc).await {
match self.lq_allow(stk, &lqctx, &lqopt, &lq, doc).await {
Err(Error::Ignore) => {
trace!("live query did not have permission to view this document, skipping");
continue;
@ -228,14 +223,14 @@ impl<'a> Document<'a> {
let lqopt: &Options = &lqopt.new_with_futures(true);
// Output the full document before any changes were applied
let mut value =
doc.doc.compute(stk, &lqctx, lqopt, txn, Some(doc)).await?;
doc.doc.compute(stk, &lqctx, lqopt, Some(doc)).await?;
// TODO(SUR-349): We need an empty object instead of Value::None for serialisation
if value.is_none() {
value = Value::Object(Default::default());
}
// Remove metadata fields on output
value.del(stk, &lqctx, lqopt, txn, &*META).await?;
value.del(stk, &lqctx, lqopt, &*META).await?;
// Output result
value
},
@ -250,7 +245,7 @@ impl<'a> Document<'a> {
.send(Notification {
id: lv.id,
action: Action::Create,
result: self.pluck(stk, &lqctx, &lqopt, txn, &lq).await?,
result: self.pluck(stk, &lqctx, &lqopt, &lq).await?,
})
.await?;
}
@ -262,7 +257,7 @@ impl<'a> Document<'a> {
.send(Notification {
id: lv.id,
action: Action::Update,
result: self.pluck(stk, &lqctx, &lqopt, txn, &lq).await?,
result: self.pluck(stk, &lqctx, &lqopt, &lq).await?,
})
.await?;
}

View file

@ -1,7 +1,7 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::Workable;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use reblessive::tree::Stk;
@ -12,7 +12,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Get the record id
@ -21,7 +20,7 @@ impl<'a> Document<'a> {
self.current.doc.to_mut().def(rid);
// This is an INSERT statement
if let Workable::Insert(v) = &self.extras {
let v = v.compute(stk, ctx, opt, txn, Some(&self.current)).await?;
let v = v.compute(stk, ctx, opt, Some(&self.current)).await?;
self.current.doc.to_mut().merge(v)?;
}
// Set default field values

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::iam::Action;
@ -20,7 +20,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Ensure futures are run
@ -36,11 +35,11 @@ impl<'a> Document<'a> {
}
Output::After => {
// Output the full document after all changes were applied
self.current.doc.compute(stk, ctx, opt, txn, Some(&self.current)).await
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
}
Output::Before => {
// Output the full document before any changes were applied
self.initial.doc.compute(stk, ctx, opt, txn, Some(&self.initial)).await
self.initial.doc.compute(stk, ctx, opt, Some(&self.initial)).await
}
Output::Fields(v) => {
// Configure the context
@ -48,28 +47,28 @@ impl<'a> Document<'a> {
ctx.add_value("after", self.current.doc.as_ref());
ctx.add_value("before", self.initial.doc.as_ref());
// Output the specified fields
v.compute(stk, &ctx, opt, txn, Some(&self.current), false).await
v.compute(stk, &ctx, opt, Some(&self.current), false).await
}
},
None => match stm {
Statement::Live(s) => match s.expr.len() {
0 => Ok(self.initial.doc.diff(&self.current.doc, Idiom::default()).into()),
_ => s.expr.compute(stk, ctx, opt, txn, Some(&self.current), false).await,
_ => s.expr.compute(stk, ctx, opt, Some(&self.current), false).await,
},
Statement::Select(s) => {
s.expr.compute(stk, ctx, opt, txn, Some(&self.current), s.group.is_some()).await
s.expr.compute(stk, ctx, opt, Some(&self.current), s.group.is_some()).await
}
Statement::Create(_) => {
self.current.doc.compute(stk, ctx, opt, txn, Some(&self.current)).await
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
}
Statement::Update(_) => {
self.current.doc.compute(stk, ctx, opt, txn, Some(&self.current)).await
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
}
Statement::Relate(_) => {
self.current.doc.compute(stk, ctx, opt, txn, Some(&self.current)).await
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
}
Statement::Insert(_) => {
self.current.doc.compute(stk, ctx, opt, txn, Some(&self.current)).await
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
}
_ => Err(Error::Ignore),
},
@ -79,13 +78,13 @@ impl<'a> Document<'a> {
// Should we run permissions checks?
if opt.check_perms(Action::View) {
// Loop through all field statements
for fd in self.fd(opt, txn).await?.iter() {
for fd in self.fd(ctx, opt).await?.iter() {
// Loop over each field in document
for k in out.each(&fd.name).iter() {
// Process the field permissions
match &fd.permissions.select {
Permission::Full => (),
Permission::None => out.del(stk, ctx, opt, txn, k).await?,
Permission::None => out.del(stk, ctx, opt, k).await?,
Permission::Specific(e) => {
// Disable permissions
let opt = &opt.new_with_perms(false);
@ -96,11 +95,11 @@ impl<'a> Document<'a> {
ctx.add_value("value", &val);
// Process the PERMISSION clause
if !e
.compute(stk, &ctx, opt, txn, Some(&self.current))
.compute(stk, &ctx, opt, Some(&self.current))
.await?
.is_truthy()
{
out.del(stk, &ctx, opt, txn, k).await?
out.del(stk, &ctx, opt, k).await?
}
}
}
@ -111,7 +110,7 @@ impl<'a> Document<'a> {
// Remove any omitted fields from output
if let Some(v) = stm.omit() {
for v in v.iter() {
out.del(stk, ctx, opt, txn, v).await?;
out.del(stk, ctx, opt, v).await?;
}
}
// Remove metadata fields on output

View file

@ -1,7 +1,7 @@
use crate::ctx::Context;
use crate::dbs::Operable;
use crate::dbs::Statement;
use crate::dbs::Workable;
use crate::dbs::{Operable, Transaction};
use crate::dbs::{Options, Processed};
use crate::doc::Document;
use crate::err::Error;
@ -14,7 +14,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
mut pro: Processed,
) -> Result<Value, Error> {
@ -30,12 +29,12 @@ impl<'a> Document<'a> {
let mut doc = Document::new(pro.rid.as_ref(), pro.ir.as_ref(), &ins.0, ins.1);
// Process the statement
let res = match stm {
Statement::Select(_) => doc.select(stk, ctx, opt, txn, stm).await,
Statement::Update(_) => doc.update(stk, ctx, opt, txn, stm).await,
Statement::Create(_) => doc.create(stk, ctx, opt, txn, stm).await,
Statement::Relate(_) => doc.relate(stk, ctx, opt, txn, stm).await,
Statement::Delete(_) => doc.delete(stk, ctx, opt, txn, stm).await,
Statement::Insert(_) => doc.insert(stk, ctx, opt, txn, stm).await,
Statement::Select(_) => doc.select(stk, ctx, opt, stm).await,
Statement::Update(_) => doc.update(stk, ctx, opt, stm).await,
Statement::Create(_) => doc.create(stk, ctx, opt, stm).await,
Statement::Relate(_) => doc.relate(stk, ctx, opt, stm).await,
Statement::Delete(_) => doc.delete(stk, ctx, opt, stm).await,
Statement::Insert(_) => doc.insert(stk, ctx, opt, stm).await,
_ => unreachable!(),
};
// Check the result
@ -46,7 +45,7 @@ impl<'a> Document<'a> {
Err(Error::RetryWithId(v)) => {
// Fetch the data from the store
let key = crate::key::thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
let val = txn.clone().lock().await.get(key).await?;
let val = ctx.tx_lock().await.get(key).await?;
// Parse the data from the store
let val = match val {
Some(v) => Value::from(v),

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::dir::Dir;
@ -19,17 +19,14 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Check if changed
if !self.changed() {
return Ok(());
}
// Clone transaction
let run = txn.clone();
// Claim transaction
let mut run = run.lock().await;
let mut run = ctx.tx_lock().await;
// Get the record id
if let Some(rid) = self.id {
// Purge the record data
@ -70,7 +67,7 @@ impl<'a> Document<'a> {
..DeleteStatement::default()
};
// Execute the delete statement
stm.compute(stk, ctx, opt, txn, None).await?;
stm.compute(stk, ctx, opt, None).await?;
}
}
}

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::value::Value;
@ -12,72 +12,71 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check if table has correct relation status
self.relation(ctx, opt, txn, stm).await?;
self.relation(ctx, opt, stm).await?;
// Check current record
match self.current.doc.is_some() {
// Create new edge
false => {
// Store record edges
self.edges(ctx, opt, txn, stm).await?;
self.edges(ctx, opt, stm).await?;
// Alter record data
self.alter(stk, ctx, opt, txn, stm).await?;
self.alter(stk, ctx, opt, stm).await?;
// Merge fields data
self.field(stk, ctx, opt, txn, stm).await?;
self.field(stk, ctx, opt, stm).await?;
// Reset fields data
self.reset(ctx, opt, txn, stm).await?;
self.reset(ctx, opt, stm).await?;
// Clean fields data
self.clean(stk, ctx, opt, txn, stm).await?;
self.clean(stk, ctx, opt, stm).await?;
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Store record data
self.store(ctx, opt, txn, stm).await?;
self.store(ctx, opt, stm).await?;
// Store index data
self.index(stk, ctx, opt, txn, stm).await?;
self.index(stk, ctx, opt, stm).await?;
// Run table queries
self.table(stk, ctx, opt, txn, stm).await?;
self.table(stk, ctx, opt, stm).await?;
// Run lives queries
self.lives(stk, ctx, opt, txn, stm).await?;
self.lives(stk, ctx, opt, stm).await?;
// Run change feeds queries
self.changefeeds(ctx, opt, txn, stm).await?;
self.changefeeds(ctx, opt, stm).await?;
// Run event queries
self.event(stk, ctx, opt, txn, stm).await?;
self.event(stk, ctx, opt, stm).await?;
// Yield document
self.pluck(stk, ctx, opt, txn, stm).await
self.pluck(stk, ctx, opt, stm).await
}
// Update old edge
true => {
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Store record edges
self.edges(ctx, opt, txn, stm).await?;
self.edges(ctx, opt, stm).await?;
// Alter record data
self.alter(stk, ctx, opt, txn, stm).await?;
self.alter(stk, ctx, opt, stm).await?;
// Merge fields data
self.field(stk, ctx, opt, txn, stm).await?;
self.field(stk, ctx, opt, stm).await?;
// Reset fields data
self.reset(ctx, opt, txn, stm).await?;
self.reset(ctx, opt, stm).await?;
// Clean fields data
self.clean(stk, ctx, opt, txn, stm).await?;
self.clean(stk, ctx, opt, stm).await?;
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Store record data
self.store(ctx, opt, txn, stm).await?;
self.store(ctx, opt, stm).await?;
// Store index data
self.index(stk, ctx, opt, txn, stm).await?;
self.index(stk, ctx, opt, stm).await?;
// Run table queries
self.table(stk, ctx, opt, txn, stm).await?;
self.table(stk, ctx, opt, stm).await?;
// Run lives queries
self.lives(stk, ctx, opt, txn, stm).await?;
self.lives(stk, ctx, opt, stm).await?;
// Run change feeds queries
self.changefeeds(ctx, opt, txn, stm).await?;
self.changefeeds(ctx, opt, stm).await?;
// Run event queries
self.event(stk, ctx, opt, txn, stm).await?;
self.event(stk, ctx, opt, stm).await?;
// Yield document
self.pluck(stk, ctx, opt, txn, stm).await
self.pluck(stk, ctx, opt, stm).await
}
}
}

View file

@ -1,18 +1,17 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
impl<'a> Document<'a> {
pub async fn relation(
&mut self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
let tb = self.tb(opt, txn).await?;
let tb = self.tb(ctx, opt).await?;
let rid = self.id.as_ref().unwrap();
match stm {

View file

@ -1,7 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::Transaction;
use crate::dbs::Workable;
use crate::doc::Document;
use crate::err::Error;
@ -15,7 +14,6 @@ impl<'a> Document<'a> {
&mut self,
_ctx: &Context<'_>,
_opt: &Options,
_txn: &Transaction,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Get the record id

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::value::Value;
@ -12,16 +12,15 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check if record exists
self.empty(ctx, opt, txn, stm).await?;
self.empty(ctx, opt, stm).await?;
// Check where clause
self.check(stk, ctx, opt, txn, stm).await?;
self.check(stk, ctx, opt, stm).await?;
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Yield document
self.pluck(stk, ctx, opt, txn, stm).await
self.pluck(stk, ctx, opt, stm).await
}
}

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::key::key_req::KeyRequirements;
@ -8,9 +8,8 @@ use crate::key::key_req::KeyRequirements;
impl<'a> Document<'a> {
pub async fn store(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
// Check if changed
@ -18,11 +17,11 @@ impl<'a> Document<'a> {
return Ok(());
}
// Check if the table is a view
if self.tb(opt, txn).await?.drop {
if self.tb(ctx, opt).await?.drop {
return Ok(());
}
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Get the record id
let rid = self.id.as_ref().unwrap();
// Store the record data

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::{Force, Statement};
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::data::Data;
@ -36,7 +36,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<(), Error> {
// Check import
@ -56,8 +55,8 @@ impl<'a> Document<'a> {
{
tb.clone()
}
Force::All => self.ft(opt, txn).await?,
_ if self.changed() => self.ft(opt, txn).await?,
Force::All => self.ft(ctx, opt).await?,
_ if self.changed() => self.ft(ctx, opt).await?,
_ => return Ok(()),
};
// Don't run permissions
@ -83,7 +82,7 @@ impl<'a> Document<'a> {
let id = stk
.scope(|scope| {
try_join_all(group.iter().map(|v| {
scope.run(|stk| v.compute(stk, ctx, opt, txn, Some(&self.initial)))
scope.run(|stk| v.compute(stk, ctx, opt, Some(&self.initial)))
}))
})
.await?
@ -99,7 +98,7 @@ impl<'a> Document<'a> {
let id = stk
.scope(|scope| {
try_join_all(group.iter().map(|v| {
scope.run(|stk| v.compute(stk, ctx, opt, txn, Some(&self.current)))
scope.run(|stk| v.compute(stk, ctx, opt, Some(&self.current)))
}))
})
.await?
@ -115,7 +114,7 @@ impl<'a> Document<'a> {
match &tb.cond {
// There is a WHERE clause specified
Some(cond) => {
match cond.compute(stk, ctx, opt, txn, Some(&self.current)).await? {
match cond.compute(stk, ctx, opt, Some(&self.current)).await? {
v if v.is_truthy() => {
if !targeted_force && act != Action::Create {
// Delete the old value
@ -124,13 +123,12 @@ impl<'a> Document<'a> {
let stm = UpdateStatement {
what: Values(vec![Value::from(old)]),
data: Some(
self.data(stk, ctx, opt, txn, act, &tb.expr)
.await?,
self.data(stk, ctx, opt, act, &tb.expr).await?,
),
..UpdateStatement::default()
};
// Execute the statement
stm.compute(stk, ctx, opt, txn, None).await?;
stm.compute(stk, ctx, opt, None).await?;
}
if act != Action::Delete {
// Update the new value
@ -139,13 +137,12 @@ impl<'a> Document<'a> {
let stm = UpdateStatement {
what: Values(vec![Value::from(rid)]),
data: Some(
self.data(stk, ctx, opt, txn, act, &tb.expr)
.await?,
self.data(stk, ctx, opt, act, &tb.expr).await?,
),
..UpdateStatement::default()
};
// Execute the statement
stm.compute(stk, ctx, opt, txn, None).await?;
stm.compute(stk, ctx, opt, None).await?;
}
}
_ => {
@ -156,13 +153,12 @@ impl<'a> Document<'a> {
let stm = UpdateStatement {
what: Values(vec![Value::from(old)]),
data: Some(
self.data(stk, ctx, opt, txn, act, &tb.expr)
.await?,
self.data(stk, ctx, opt, act, &tb.expr).await?,
),
..UpdateStatement::default()
};
// Execute the statement
stm.compute(stk, ctx, opt, txn, None).await?;
stm.compute(stk, ctx, opt, None).await?;
}
}
}
@ -175,11 +171,11 @@ impl<'a> Document<'a> {
// Modify the value in the table
let stm = UpdateStatement {
what: Values(vec![Value::from(old)]),
data: Some(self.data(stk, ctx, opt, txn, act, &tb.expr).await?),
data: Some(self.data(stk, ctx, opt, act, &tb.expr).await?),
..UpdateStatement::default()
};
// Execute the statement
stm.compute(stk, ctx, opt, txn, None).await?;
stm.compute(stk, ctx, opt, None).await?;
}
if act != Action::Delete {
// Update the new value
@ -187,11 +183,11 @@ impl<'a> Document<'a> {
// Modify the value in the table
let stm = UpdateStatement {
what: Values(vec![Value::from(rid)]),
data: Some(self.data(stk, ctx, opt, txn, act, &tb.expr).await?),
data: Some(self.data(stk, ctx, opt, act, &tb.expr).await?),
..UpdateStatement::default()
};
// Execute the statement
stm.compute(stk, ctx, opt, txn, None).await?;
stm.compute(stk, ctx, opt, None).await?;
}
}
}
@ -207,7 +203,7 @@ impl<'a> Document<'a> {
match &tb.cond {
// There is a WHERE clause specified
Some(cond) => {
match cond.compute(stk, ctx, opt, txn, Some(&self.current)).await? {
match cond.compute(stk, ctx, opt, Some(&self.current)).await? {
v if v.is_truthy() => {
// Define the statement
let stm = match act {
@ -219,14 +215,12 @@ impl<'a> Document<'a> {
// Update the value in the table
_ => Query::Update(UpdateStatement {
what: Values(vec![Value::from(rid)]),
data: Some(
self.full(stk, ctx, opt, txn, &tb.expr).await?,
),
data: Some(self.full(stk, ctx, opt, &tb.expr).await?),
..UpdateStatement::default()
}),
};
// Execute the statement
stm.compute(stk, ctx, opt, txn, None).await?;
stm.compute(stk, ctx, opt, None).await?;
}
_ => {
// Delete the value in the table
@ -235,7 +229,7 @@ impl<'a> Document<'a> {
..DeleteStatement::default()
};
// Execute the statement
stm.compute(stk, ctx, opt, txn, None).await?;
stm.compute(stk, ctx, opt, None).await?;
}
}
}
@ -251,12 +245,12 @@ impl<'a> Document<'a> {
// Update the value in the table
_ => Query::Update(UpdateStatement {
what: Values(vec![Value::from(rid)]),
data: Some(self.full(stk, ctx, opt, txn, &tb.expr).await?),
data: Some(self.full(stk, ctx, opt, &tb.expr).await?),
..UpdateStatement::default()
}),
};
// Execute the statement
stm.compute(stk, ctx, opt, txn, None).await?;
stm.compute(stk, ctx, opt, None).await?;
}
}
}
@ -271,10 +265,9 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
exp: &Fields,
) -> Result<Data, Error> {
let mut data = exp.compute(stk, ctx, opt, txn, Some(&self.current), false).await?;
let mut data = exp.compute(stk, ctx, opt, Some(&self.current), false).await?;
data.cut(ID.as_ref());
Ok(Data::ReplaceExpression(data))
}
@ -284,7 +277,6 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
act: Action,
exp: &Fields,
) -> Result<Data, Error> {
@ -314,29 +306,29 @@ impl<'a> Document<'a> {
match expr {
Value::Function(f) if f.is_rolling() => match f.name() {
Some("count") => {
let val = f.compute(stk, ctx, opt, txn, doc).await?;
let val = f.compute(stk, ctx, opt, doc).await?;
self.chg(&mut ops, &act, idiom, val);
}
Some("math::sum") => {
let val = f.args()[0].compute(stk, ctx, opt, txn, doc).await?;
let val = f.args()[0].compute(stk, ctx, opt, doc).await?;
self.chg(&mut ops, &act, idiom, val);
}
Some("math::min") | Some("time::min") => {
let val = f.args()[0].compute(stk, ctx, opt, txn, doc).await?;
let val = f.args()[0].compute(stk, ctx, opt, doc).await?;
self.min(&mut ops, &act, idiom, val);
}
Some("math::max") | Some("time::max") => {
let val = f.args()[0].compute(stk, ctx, opt, txn, doc).await?;
let val = f.args()[0].compute(stk, ctx, opt, doc).await?;
self.max(&mut ops, &act, idiom, val);
}
Some("math::mean") => {
let val = f.args()[0].compute(stk, ctx, opt, txn, doc).await?;
let val = f.args()[0].compute(stk, ctx, opt, doc).await?;
self.mean(&mut ops, &act, idiom, val);
}
_ => unreachable!(),
},
_ => {
let val = expr.compute(stk, ctx, opt, txn, doc).await?;
let val = expr.compute(stk, ctx, opt, doc).await?;
self.set(&mut ops, idiom, val);
}
}

View file

@ -1,6 +1,6 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::{Options, Transaction};
use crate::doc::Document;
use crate::err::Error;
use crate::sql::value::Value;
@ -12,36 +12,35 @@ impl<'a> Document<'a> {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check where clause
self.check(stk, ctx, opt, txn, stm).await?;
self.check(stk, ctx, opt, stm).await?;
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Alter record data
self.alter(stk, ctx, opt, txn, stm).await?;
self.alter(stk, ctx, opt, stm).await?;
// Merge fields data
self.field(stk, ctx, opt, txn, stm).await?;
self.field(stk, ctx, opt, stm).await?;
// Reset fields data
self.reset(ctx, opt, txn, stm).await?;
self.reset(ctx, opt, stm).await?;
// Clean fields data
self.clean(stk, ctx, opt, txn, stm).await?;
self.clean(stk, ctx, opt, stm).await?;
// Check if allowed
self.allow(stk, ctx, opt, txn, stm).await?;
self.allow(stk, ctx, opt, stm).await?;
// Store record data
self.store(ctx, opt, txn, stm).await?;
self.store(ctx, opt, stm).await?;
// Store index data
self.index(stk, ctx, opt, txn, stm).await?;
self.index(stk, ctx, opt, stm).await?;
// Run table queries
self.table(stk, ctx, opt, txn, stm).await?;
self.table(stk, ctx, opt, stm).await?;
// Run lives queries
self.lives(stk, ctx, opt, txn, stm).await?;
self.lives(stk, ctx, opt, stm).await?;
// Run change feeds queries
self.changefeeds(ctx, opt, txn, stm).await?;
self.changefeeds(ctx, opt, stm).await?;
// Run event queries
self.event(stk, ctx, opt, txn, stm).await?;
self.event(stk, ctx, opt, stm).await?;
// Yield document
self.pluck(stk, ctx, opt, txn, stm).await
self.pluck(stk, ctx, opt, stm).await
}
}

View file

@ -1,7 +1,6 @@
//! Executes functions from SQL. If there is an SQL function it will be defined in this module.
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Transaction;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::idx::planner::executor::QueryExecutor;
@ -40,7 +39,6 @@ pub async fn run(
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
name: &str,
args: Vec<Value>,
@ -55,7 +53,7 @@ pub async fn run(
|| name.starts_with("crypto::pbkdf2")
|| name.starts_with("crypto::scrypt")
{
stk.run(|stk| asynchronous(stk, ctx, Some(opt), Some(txn), doc, name, args)).await
stk.run(|stk| asynchronous(stk, ctx, Some(opt), doc, name, args)).await
} else {
synchronous(ctx, doc, name, args)
}
@ -385,7 +383,6 @@ pub async fn asynchronous(
stk: &mut Stk,
ctx: &Context<'_>,
opt: Option<&Options>,
txn: Option<&Transaction>,
doc: Option<&CursorDoc<'_>>,
name: &str,
args: Vec<Value>,
@ -425,15 +422,15 @@ pub async fn asynchronous(
"http::patch" => http::patch(ctx).await,
"http::delete" => http::delete(ctx).await,
//
"search::analyze" => search::analyze((stk,ctx, txn, opt)).await,
"search::score" => search::score((ctx, txn, doc)).await,
"search::highlight" => search::highlight((ctx,txn, doc)).await,
"search::offsets" => search::offsets((ctx, txn, doc)).await,
"search::analyze" => search::analyze((stk,ctx, opt)).await,
"search::score" => search::score((ctx, doc)).await,
"search::highlight" => search::highlight((ctx, doc)).await,
"search::offsets" => search::offsets((ctx, doc)).await,
//
"sleep" => sleep::sleep(ctx).await,
//
"type::field" => r#type::field((stk,ctx, opt, txn, doc)).await,
"type::fields" => r#type::fields((stk,ctx, opt, txn, doc)).await,
"type::field" => r#type::field((stk,ctx, opt, doc)).await,
"type::fields" => r#type::fields((stk,ctx, opt, doc)).await,
)
}

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::idx::planner::executor::QueryExecutor;
@ -211,12 +211,10 @@ fn get_executor_option<'a>(
ExecutorOption::None
}
#[allow(clippy::too_many_arguments)]
pub(crate) async fn matches(
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
exp: &Expression,
l: Value,
@ -225,9 +223,7 @@ pub(crate) async fn matches(
let res = match get_executor_option(ctx, doc, exp) {
ExecutorOption::PreMatch => true,
ExecutorOption::None => false,
ExecutorOption::Execute(exe, thg) => {
exe.matches(stk, ctx, opt, txn, thg, exp, l, r).await?
}
ExecutorOption::Execute(exe, thg) => exe.matches(stk, ctx, opt, thg, exp, l, r).await?,
};
Ok(res.into())
}
@ -236,14 +232,13 @@ pub(crate) async fn knn(
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
exp: &Expression,
) -> Result<Value, Error> {
match get_executor_option(ctx, doc, exp) {
ExecutorOption::PreMatch => Ok(Value::Bool(true)),
ExecutorOption::None => Ok(Value::Bool(false)),
ExecutorOption::Execute(exe, thg) => exe.knn(stk, ctx, opt, txn, thg, doc, exp).await,
ExecutorOption::Execute(exe, thg) => exe.knn(stk, ctx, opt, thg, doc, exp).await,
}
}

View file

@ -7,7 +7,7 @@ use super::modules::resolver;
use super::modules::surrealdb::query::QueryContext;
use super::modules::surrealdb::query::QUERY_DATA_PROP_NAME;
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::value::Value;
@ -24,7 +24,6 @@ use js::{Class, Ctx, Function, Module, Promise};
pub unsafe fn create_query_data<'a>(
context: &'a Context<'a>,
opt: &'a Options,
txn: &'a Transaction,
doc: Option<&'a CursorDoc<'a>>,
ctx: &Ctx<'_>,
) -> Result<(), js::Error> {
@ -36,7 +35,6 @@ pub unsafe fn create_query_data<'a>(
QueryContext {
context,
opt,
txn,
doc,
},
)?;
@ -51,7 +49,6 @@ pub unsafe fn create_query_data<'a>(
pub async fn run(
context: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
src: &str,
arg: Vec<Value>,
@ -88,7 +85,7 @@ pub async fn run(
// SAFETY: This is safe because the runtime only lives for the duration of this
// function. For the entire duration of which context, opt, txn and doc are valid.
unsafe{ create_query_data(context,opt,txn,doc,&ctx) }?;
unsafe{ create_query_data(context,opt,doc,&ctx) }?;
// Register the surrealdb module as a global object
let (module,promise) = Module::evaluate_def::<modules::surrealdb::Package, _>(ctx.clone(), "surrealdb")?;
promise.finish::<()>()?;

View file

@ -73,7 +73,7 @@ async fn fut(js_ctx: js::Ctx<'_>, name: &str, args: Vec<Value>) -> Result<Value>
let this = js_ctx.globals().get::<_, OwnedBorrow<QueryContext>>(QUERY_DATA_PROP_NAME)?;
// Process the called function
let res = Stk::enter_run(|stk| {
fnc::asynchronous(stk, this.context, Some(this.opt), Some(this.txn), this.doc, name, args)
fnc::asynchronous(stk, this.context, Some(this.opt), this.doc, name, args)
})
.await;
// Convert any response error

View file

@ -19,7 +19,7 @@ async fn value(ctx: Ctx<'_>, value: Coerced<String>) -> Result<SurValue> {
let this = ctx.globals().get::<_, OwnedBorrow<QueryContext>>(QUERY_DATA_PROP_NAME)?;
let value = Stk::enter_run(|stk| async {
value
.compute(stk, this.context, this.opt, this.txn, this.doc)
.compute(stk, this.context, this.opt, this.doc)
.await
.map_err(|e| Exception::throw_message(&ctx, &e.to_string()))
})

View file

@ -7,7 +7,7 @@ use reblessive::tree::Stk;
use crate::{
ctx::Context,
dbs::{Attach, Options, Transaction},
dbs::{Attach, Options},
doc::CursorDoc,
sql::Value as SurValue,
};
@ -24,7 +24,6 @@ pub const QUERY_DATA_PROP_NAME: &str = "__query_context__";
pub struct QueryContext<'js> {
pub context: &'js Context<'js>,
pub opt: &'js Options,
pub txn: &'js Transaction,
pub doc: Option<&'js CursorDoc<'js>>,
}
@ -78,9 +77,8 @@ pub async fn query<'js>(
.attach(context)
.map_err(|e| Exception::throw_message(&ctx, &e.to_string()))?;
let value =
Stk::enter_run(|stk| query.query.compute(stk, &context, this.opt, this.txn, this.doc))
.await
.map_err(|e| Exception::throw_message(&ctx, &e.to_string()))?;
let value = Stk::enter_run(|stk| query.query.compute(stk, &context, this.opt, this.doc))
.await
.map_err(|e| Exception::throw_message(&ctx, &e.to_string()))?;
Result::Ok(value)
}

View file

@ -1,61 +1,54 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::fnc::get_execution_context;
use crate::idx::ft::analyzer::Analyzer;
use crate::idx::ft::highlighter::HighlightParams;
use crate::sql::Value;
use reblessive::tree::Stk;
pub async fn analyze(
(stk, ctx, txn, opt): (&mut Stk, &Context<'_>, Option<&Transaction>, Option<&Options>),
(stk, ctx, opt): (&mut Stk, &Context<'_>, Option<&Options>),
(az, val): (Value, Value),
) -> Result<Value, Error> {
if let (Some(txn), Some(opt), Value::Strand(az), Value::Strand(val)) = (txn, opt, az, val) {
if let (Some(opt), Value::Strand(az), Value::Strand(val)) = (opt, az, val) {
let az: Analyzer =
txn.lock().await.get_db_analyzer(opt.ns(), opt.db(), az.as_str()).await?.into();
az.analyze(stk, ctx, opt, txn, val.0).await
ctx.tx_lock().await.get_db_analyzer(opt.ns(), opt.db(), az.as_str()).await?.into();
az.analyze(stk, ctx, opt, val.0).await
} else {
Ok(Value::None)
}
}
pub async fn score(
(ctx, txn, doc): (&Context<'_>, Option<&Transaction>, Option<&CursorDoc<'_>>),
(ctx, doc): (&Context<'_>, Option<&CursorDoc<'_>>),
(match_ref,): (Value,),
) -> Result<Value, Error> {
if let Some(txn) = txn {
if let Some((exe, doc, thg)) = get_execution_context(ctx, doc) {
return exe.score(txn, &match_ref, thg, doc.ir).await;
}
if let Some((exe, doc, thg)) = get_execution_context(ctx, doc) {
return exe.score(ctx, &match_ref, thg, doc.ir).await;
}
Ok(Value::None)
}
pub async fn highlight(
(ctx, txn, doc): (&Context<'_>, Option<&Transaction>, Option<&CursorDoc<'_>>),
(prefix, suffix, match_ref, partial): (Value, Value, Value, Option<Value>),
(ctx, doc): (&Context<'_>, Option<&CursorDoc<'_>>),
args: (Value, Value, Value, Option<Value>),
) -> Result<Value, Error> {
if let Some(txn) = txn {
if let Some((exe, doc, thg)) = get_execution_context(ctx, doc) {
let partial = partial.map(|p| p.convert_to_bool()).unwrap_or(Ok(false))?;
return exe
.highlight(txn, thg, prefix, suffix, match_ref, partial, doc.doc.as_ref())
.await;
}
if let Some((exe, doc, thg)) = get_execution_context(ctx, doc) {
let hlp: HighlightParams = args.try_into()?;
return exe.highlight(ctx, thg, hlp, doc.doc.as_ref()).await;
}
Ok(Value::None)
}
pub async fn offsets(
(ctx, txn, doc): (&Context<'_>, Option<&Transaction>, Option<&CursorDoc<'_>>),
(ctx, doc): (&Context<'_>, Option<&CursorDoc<'_>>),
(match_ref, partial): (Value, Option<Value>),
) -> Result<Value, Error> {
if let Some(txn) = txn {
if let Some((exe, _, thg)) = get_execution_context(ctx, doc) {
let partial = partial.map(|p| p.convert_to_bool()).unwrap_or(Ok(false))?;
return exe.offsets(txn, thg, match_ref, partial).await;
}
if let Some((exe, _, thg)) = get_execution_context(ctx, doc) {
let partial = partial.map(|p| p.convert_to_bool()).unwrap_or(Ok(false))?;
return exe.offsets(ctx, thg, match_ref, partial).await;
}
Ok(Value::None)
}

View file

@ -1,7 +1,7 @@
use std::ops::Bound;
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::table::Table;
@ -28,22 +28,16 @@ pub fn duration((val,): (Value,)) -> Result<Value, Error> {
}
pub async fn field(
(stk, ctx, opt, txn, doc): (
&mut Stk,
&Context<'_>,
Option<&Options>,
Option<&Transaction>,
Option<&CursorDoc<'_>>,
),
(stk, ctx, opt, doc): (&mut Stk, &Context<'_>, Option<&Options>, Option<&CursorDoc<'_>>),
(val,): (String,),
) -> Result<Value, Error> {
match (opt, txn) {
(Some(opt), Some(txn)) => {
match opt {
Some(opt) => {
// Parse the string as an Idiom
let idi = syn::idiom(&val)?;
// Return the Idiom or fetch the field
match opt.projections {
true => Ok(idi.compute(stk, ctx, opt, txn, doc).await?),
true => Ok(idi.compute(stk, ctx, opt, doc).await?),
false => Ok(idi.into()),
}
}
@ -52,24 +46,18 @@ pub async fn field(
}
pub async fn fields(
(stk, ctx, opt, txn, doc): (
&mut Stk,
&Context<'_>,
Option<&Options>,
Option<&Transaction>,
Option<&CursorDoc<'_>>,
),
(stk, ctx, opt, doc): (&mut Stk, &Context<'_>, Option<&Options>, Option<&CursorDoc<'_>>),
(val,): (Vec<String>,),
) -> Result<Value, Error> {
match (opt, txn) {
(Some(opt), Some(txn)) => {
match opt {
Some(opt) => {
let mut args: Vec<Value> = Vec::with_capacity(val.len());
for v in val {
// Parse the string as an Idiom
let idi = syn::idiom(&v)?;
// Return the Idiom or fetch the field
match opt.projections {
true => args.push(idi.compute(stk, ctx, opt, txn, doc).await?),
true => args.push(idi.compute(stk, ctx, opt, doc).await?),
false => args.push(idi.into()),
}
}

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::err::Error;
use crate::idx::ft::analyzer::filter::FilteringStage;
use crate::idx::ft::analyzer::tokenizer::{Tokenizer, Tokens};
@ -64,17 +64,15 @@ impl Analyzer {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
t: &Terms,
content: String,
) -> Result<(TermsList, TermsSet), Error> {
let tokens =
self.generate_tokens(stk, ctx, opt, txn, FilteringStage::Querying, content).await?;
let tokens = self.generate_tokens(stk, ctx, opt, FilteringStage::Querying, content).await?;
// We extract the term ids
let mut list = Vec::with_capacity(tokens.list().len());
let mut unique_tokens = HashSet::new();
let mut set = HashSet::new();
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
let mut has_unknown_terms = false;
for token in tokens.list() {
// Tokens can contains duplicated, not need to evaluate them again
@ -104,15 +102,14 @@ impl Analyzer {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
t: &Terms,
content: Value,
) -> Result<TermsSet, Error> {
let mut tv = Vec::new();
self.analyze_value(stk, ctx, opt, txn, content, FilteringStage::Indexing, &mut tv).await?;
self.analyze_value(stk, ctx, opt, content, FilteringStage::Indexing, &mut tv).await?;
let mut set = HashSet::new();
let mut has_unknown_terms = false;
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
for tokens in tv {
for token in tokens.list() {
if let Some(term_id) =
@ -138,7 +135,6 @@ impl Analyzer {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
terms: &mut Terms,
field_content: Vec<Value>,
) -> Result<(DocLength, Vec<(TermId, TermFrequency)>), Error> {
@ -146,16 +142,8 @@ impl Analyzer {
// Let's first collect all the inputs, and collect the tokens.
// We need to store them because everything after is zero-copy
let mut inputs = vec![];
self.analyze_content(
stk,
ctx,
opt,
txn,
field_content,
FilteringStage::Indexing,
&mut inputs,
)
.await?;
self.analyze_content(stk, ctx, opt, field_content, FilteringStage::Indexing, &mut inputs)
.await?;
// We then collect every unique terms and count the frequency
let mut tf: HashMap<&str, TermFrequency> = HashMap::new();
for tks in &inputs {
@ -174,7 +162,7 @@ impl Analyzer {
}
// Now we can resolve the term ids
let mut tfid = Vec::with_capacity(tf.len());
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
for (t, f) in tf {
tfid.push((terms.resolve_term_id(&mut tx, t).await?, f));
}
@ -189,7 +177,6 @@ impl Analyzer {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
terms: &mut Terms,
content: Vec<Value>,
) -> Result<(DocLength, Vec<(TermId, TermFrequency)>, Vec<(TermId, OffsetRecords)>), Error> {
@ -197,8 +184,7 @@ impl Analyzer {
// Let's first collect all the inputs, and collect the tokens.
// We need to store them because everything after is zero-copy
let mut inputs = Vec::with_capacity(content.len());
self.analyze_content(stk, ctx, opt, txn, content, FilteringStage::Indexing, &mut inputs)
.await?;
self.analyze_content(stk, ctx, opt, content, FilteringStage::Indexing, &mut inputs).await?;
// We then collect every unique terms and count the frequency and extract the offsets
let mut tfos: HashMap<&str, Vec<Offset>> = HashMap::new();
for (i, tks) in inputs.iter().enumerate() {
@ -218,7 +204,7 @@ impl Analyzer {
// Now we can resolve the term ids
let mut tfid = Vec::with_capacity(tfos.len());
let mut osid = Vec::with_capacity(tfos.len());
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
for (t, o) in tfos {
let id = terms.resolve_term_id(&mut tx, t).await?;
tfid.push((id, o.len() as TermFrequency));
@ -229,53 +215,47 @@ impl Analyzer {
}
/// Was marked recursive
#[allow(clippy::too_many_arguments)]
async fn analyze_content(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
content: Vec<Value>,
stage: FilteringStage,
tks: &mut Vec<Tokens>,
) -> Result<(), Error> {
for v in content {
self.analyze_value(stk, ctx, opt, txn, v, stage, tks).await?;
self.analyze_value(stk, ctx, opt, v, stage, tks).await?;
}
Ok(())
}
/// Was marked recursive
#[allow(clippy::too_many_arguments)]
async fn analyze_value(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
val: Value,
stage: FilteringStage,
tks: &mut Vec<Tokens>,
) -> Result<(), Error> {
match val {
Value::Strand(s) => {
tks.push(self.generate_tokens(stk, ctx, opt, txn, stage, s.0).await?)
}
Value::Strand(s) => tks.push(self.generate_tokens(stk, ctx, opt, stage, s.0).await?),
Value::Number(n) => {
tks.push(self.generate_tokens(stk, ctx, opt, txn, stage, n.to_string()).await?)
tks.push(self.generate_tokens(stk, ctx, opt, stage, n.to_string()).await?)
}
Value::Bool(b) => {
tks.push(self.generate_tokens(stk, ctx, opt, txn, stage, b.to_string()).await?)
tks.push(self.generate_tokens(stk, ctx, opt, stage, b.to_string()).await?)
}
Value::Array(a) => {
for v in a.0 {
stk.run(|stk| self.analyze_value(stk, ctx, opt, txn, v, stage, tks)).await?;
stk.run(|stk| self.analyze_value(stk, ctx, opt, v, stage, tks)).await?;
}
}
Value::Object(o) => {
for (_, v) in o.0 {
stk.run(|stk| self.analyze_value(stk, ctx, opt, txn, v, stage, tks)).await?;
stk.run(|stk| self.analyze_value(stk, ctx, opt, v, stage, tks)).await?;
}
}
_ => {}
@ -288,13 +268,12 @@ impl Analyzer {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
stage: FilteringStage,
mut input: String,
) -> Result<Tokens, Error> {
if let Some(function_name) = self.function.clone() {
let fns = Function::Custom(function_name.clone(), vec![Value::Strand(Strand(input))]);
let val = fns.compute(stk, ctx, opt, txn, None).await?;
let val = fns.compute(stk, ctx, opt, None).await?;
if let Value::Strand(val) = val {
input = val.0;
} else {
@ -319,10 +298,9 @@ impl Analyzer {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
input: String,
) -> Result<Value, Error> {
self.generate_tokens(stk, ctx, opt, txn, FilteringStage::Indexing, input).await?.try_into()
self.generate_tokens(stk, ctx, opt, FilteringStage::Indexing, input).await?.try_into()
}
}
@ -345,6 +323,7 @@ mod tests {
let ds = Datastore::new("memory").await.unwrap();
let tx = ds.transaction(TransactionType::Read, LockType::Optimistic).await.unwrap();
let txn: Transaction = Arc::new(Mutex::new(tx));
let ctx = Context::default().set_transaction(txn);
let mut stmt = syn::parse(&format!("DEFINE {def}")).unwrap();
let Some(Statement::Define(DefineStatement::Analyzer(az))) = stmt.0 .0.pop() else {
@ -354,18 +333,10 @@ mod tests {
let mut stack = reblessive::TreeStack::new();
let ctx = Context::default();
let opts = Options::default();
stack
.enter(|stk| {
a.generate_tokens(
stk,
&ctx,
&opts,
&txn,
FilteringStage::Indexing,
input.to_string(),
)
a.generate_tokens(stk, &ctx, &opts, FilteringStage::Indexing, input.to_string())
})
.finish()
.await

View file

@ -6,6 +6,35 @@ use std::collections::hash_map::Entry as HEntry;
use std::collections::BTreeMap;
use std::collections::HashMap;
pub(crate) struct HighlightParams {
prefix: Value,
suffix: Value,
match_ref: Value,
partial: bool,
}
impl TryFrom<(Value, Value, Value, Option<Value>)> for HighlightParams {
type Error = Error;
fn try_from(
(prefix, suffix, match_ref, partial): (Value, Value, Value, Option<Value>),
) -> Result<Self, Error> {
let partial = partial.map(|p| p.convert_to_bool()).unwrap_or(Ok(false))?;
Ok(Self {
prefix,
suffix,
match_ref,
partial,
})
}
}
impl HighlightParams {
pub(crate) fn match_ref(&self) -> &Value {
&self.match_ref
}
}
pub(super) struct Highlighter {
prefix: Vec<char>,
suffix: Vec<char>,
@ -14,22 +43,16 @@ pub(super) struct Highlighter {
}
impl Highlighter {
pub(super) fn new(
prefix: Value,
suffix: Value,
partial: bool,
idiom: &Idiom,
doc: &Value,
) -> Self {
let prefix = prefix.to_raw_string().chars().collect();
let suffix = suffix.to_raw_string().chars().collect();
pub(super) fn new(hlp: HighlightParams, idiom: &Idiom, doc: &Value) -> Self {
let prefix = hlp.prefix.to_raw_string().chars().collect();
let suffix = hlp.suffix.to_raw_string().chars().collect();
// Extract the fields we want to highlight
let fields = doc.walk(idiom);
Self {
fields,
prefix,
suffix,
offseter: Offseter::new(partial),
offseter: Offseter::new(hlp.partial),
}
}

View file

@ -1,6 +1,6 @@
pub(crate) mod analyzer;
mod doclength;
mod highlighter;
pub(crate) mod highlighter;
mod offsets;
mod postings;
pub(super) mod scorer;
@ -8,12 +8,12 @@ pub(super) mod termdocs;
pub(crate) mod terms;
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::err::Error;
use crate::idx::docids::{DocId, DocIds};
use crate::idx::ft::analyzer::{Analyzer, TermsList, TermsSet};
use crate::idx::ft::doclength::DocLengths;
use crate::idx::ft::highlighter::{Highlighter, Offseter};
use crate::idx::ft::highlighter::{HighlightParams, Highlighter, Offseter};
use crate::idx::ft::offsets::Offsets;
use crate::idx::ft::postings::Postings;
use crate::idx::ft::scorer::BM25Scorer;
@ -98,17 +98,17 @@ impl VersionedSerdeState for State {}
impl FtIndex {
pub(crate) async fn new(
ixs: &IndexStores,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
az: &str,
index_key_base: IndexKeyBase,
p: &SearchParams,
tt: TransactionType,
) -> Result<Self, Error> {
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
let az = tx.get_db_analyzer(opt.ns(), opt.db(), az).await?;
let res = Self::with_analyzer(ixs, &mut tx, az, index_key_base, p, tt).await;
let res =
Self::with_analyzer(ctx.get_index_stores(), &mut tx, az, index_key_base, p, tt).await;
drop(tx);
res
}
@ -191,10 +191,10 @@ impl FtIndex {
pub(crate) async fn remove_document(
&mut self,
txn: &Transaction,
ctx: &Context<'_>,
rid: &Thing,
) -> Result<(), Error> {
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
// Extract and remove the doc_id (if any)
let mut doc_ids = self.doc_ids.write().await;
let doc_id = doc_ids.remove_doc(&mut tx, rid.into()).await?;
@ -244,12 +244,11 @@ impl FtIndex {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
rid: &Thing,
content: Vec<Value>,
) -> Result<(), Error> {
// Resolve the doc_id
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
let mut doc_ids = self.doc_ids.write().await;
let resolved = doc_ids.resolve_doc_id(&mut tx, rid.into()).await?;
drop(doc_ids);
@ -261,19 +260,19 @@ impl FtIndex {
let (doc_length, terms_and_frequencies, offsets) = if self.highlighting {
let (dl, tf, ofs) = self
.analyzer
.extract_terms_with_frequencies_with_offsets(stk, ctx, opt, txn, &mut t, content)
.extract_terms_with_frequencies_with_offsets(stk, ctx, opt, &mut t, content)
.await?;
(dl, tf, Some(ofs))
} else {
let (dl, tf) = self
.analyzer
.extract_terms_with_frequencies(stk, ctx, opt, txn, &mut t, content)
.extract_terms_with_frequencies(stk, ctx, opt, &mut t, content)
.await?;
(dl, tf, None)
};
// Set the doc length
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
let mut dl = self.doc_lengths.write().await;
if resolved.was_existing() {
if let Some(old_doc_length) = dl.get_doc_length_mut(&mut tx, doc_id).await? {
@ -356,12 +355,10 @@ impl FtIndex {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
query_string: String,
) -> Result<(TermsList, TermsSet), Error> {
let t = self.terms.read().await;
let res =
self.analyzer.extract_querying_terms(stk, ctx, opt, txn, &t, query_string).await?;
let res = self.analyzer.extract_querying_terms(stk, ctx, opt, &t, query_string).await?;
drop(t);
Ok(res)
}
@ -425,15 +422,12 @@ impl FtIndex {
Ok(None)
}
#[allow(clippy::too_many_arguments)]
pub(super) async fn highlight(
&self,
tx: &mut kvs::Transaction,
thg: &Thing,
terms: &[Option<(TermId, TermLen)>],
prefix: Value,
suffix: Value,
partial: bool,
hlp: HighlightParams,
idiom: &Idiom,
doc: &Value,
) -> Result<Value, Error> {
@ -442,7 +436,7 @@ impl FtIndex {
let doc_id = di.get_doc_id(tx, doc_key).await?;
drop(di);
if let Some(doc_id) = doc_id {
let mut hl = Highlighter::new(prefix, suffix, partial, idiom, doc);
let mut hl = Highlighter::new(hlp, idiom, doc);
for (term_id, term_len) in terms.iter().flatten() {
let o = self.offsets.get_offsets(tx, doc_id, *term_id).await?;
if let Some(o) = o {
@ -478,9 +472,9 @@ impl FtIndex {
Ok(Value::None)
}
pub(crate) async fn statistics(&self, txn: &Transaction) -> Result<FtStatistics, Error> {
pub(crate) async fn statistics(&self, ctx: &Context<'_>) -> Result<FtStatistics, Error> {
// TODO do parallel execution
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
let res = FtStatistics {
doc_ids: self.doc_ids.read().await.statistics(&mut run).await?,
terms: self.terms.read().await.statistics(&mut run).await?,
@ -491,8 +485,8 @@ impl FtIndex {
Ok(res)
}
pub(crate) async fn finish(&self, tx: &Transaction) -> Result<(), Error> {
let mut run = tx.lock().await;
pub(crate) async fn finish(&self, ctx: &Context<'_>) -> Result<(), Error> {
let mut run = ctx.tx_lock().await;
self.doc_ids.write().await.finish(&mut run).await?;
self.doc_lengths.write().await.finish(&mut run).await?;
self.postings.write().await.finish(&mut run).await?;
@ -543,7 +537,7 @@ impl HitsIterator {
#[cfg(test)]
mod tests {
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::idx::ft::scorer::{BM25Scorer, Score};
use crate::idx::ft::{FtIndex, HitsIterator};
use crate::idx::IndexKeyBase;
@ -559,12 +553,12 @@ mod tests {
use test_log::test;
async fn check_hits(
txn: &Transaction,
ctx: &Context<'_>,
hits: Option<HitsIterator>,
scr: BM25Scorer,
e: Vec<(&Thing, Option<Score>)>,
) {
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
if let Some(mut hits) = hits {
let mut map = HashMap::new();
while let Some((k, d)) = hits.next(&mut tx).await.unwrap() {
@ -585,13 +579,12 @@ mod tests {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
fti: &FtIndex,
qs: &str,
) -> (Option<HitsIterator>, BM25Scorer) {
let (term_list, _) =
fti.extract_querying_terms(stk, ctx, opt, txn, qs.to_string()).await.unwrap();
let mut tx = txn.lock().await;
fti.extract_querying_terms(stk, ctx, opt, qs.to_string()).await.unwrap();
let mut tx = ctx.tx_lock().await;
let td = Arc::new(fti.get_terms_docs(&mut tx, &term_list).await.unwrap());
drop(tx);
let scr = fti.new_scorer(td.clone()).unwrap().unwrap();
@ -605,11 +598,9 @@ mod tests {
az: &DefineAnalyzerStatement,
order: u32,
hl: bool,
) -> (Context<'a>, Options, Transaction, FtIndex) {
let ctx = Context::default();
let tx = ds.transaction(tt, Optimistic).await.unwrap();
let txn = Arc::new(Mutex::new(tx));
let mut tx = txn.lock().await;
) -> (Context<'a>, Options, FtIndex) {
let mut ctx = Context::default();
let mut tx = ds.transaction(tt, Optimistic).await.unwrap();
let fti = FtIndex::with_analyzer(
ctx.get_index_stores(),
&mut tx,
@ -632,15 +623,15 @@ mod tests {
)
.await
.unwrap();
drop(tx);
(ctx, Options::default(), txn, fti)
let txn = Arc::new(Mutex::new(tx));
ctx.set_transaction_mut(txn);
(ctx, Options::default(), fti)
}
pub(super) async fn finish(txn: &Transaction, fti: FtIndex) {
fti.finish(txn).await.unwrap();
let mut tx = txn.lock().await;
pub(super) async fn finish(ctx: &Context<'_>, fti: FtIndex) {
fti.finish(ctx).await.unwrap();
let mut tx = ctx.tx_lock().await;
tx.commit().await.unwrap();
drop(tx);
}
#[test(tokio::test)]
@ -661,19 +652,12 @@ mod tests {
stack
.enter(|stk| async {
// Add one document
let (ctx, opt, txn, mut fti) =
let (ctx, opt, mut fti) =
tx_fti(&ds, TransactionType::Write, &az, btree_order, false).await;
fti.index_document(
stk,
&ctx,
&opt,
&txn,
&doc1,
vec![Value::from("hello the world")],
)
.await
.unwrap();
finish(&txn, fti).await;
fti.index_document(stk, &ctx, &opt, &doc1, vec![Value::from("hello the world")])
.await
.unwrap();
finish(&ctx, fti).await;
})
.finish()
.await;
@ -681,60 +665,53 @@ mod tests {
stack
.enter(|stk| async {
// Add two documents
let (ctx, opt, txn, mut fti) =
let (ctx, opt, mut fti) =
tx_fti(&ds, TransactionType::Write, &az, btree_order, false).await;
fti.index_document(
stk,
&ctx,
&opt,
&txn,
&doc2,
vec![Value::from("a yellow hello")],
)
.await
.unwrap();
fti.index_document(stk, &ctx, &opt, &txn, &doc3, vec![Value::from("foo bar")])
fti.index_document(stk, &ctx, &opt, &doc2, vec![Value::from("a yellow hello")])
.await
.unwrap();
finish(&txn, fti).await;
fti.index_document(stk, &ctx, &opt, &doc3, vec![Value::from("foo bar")])
.await
.unwrap();
finish(&ctx, fti).await;
})
.finish()
.await;
stack
.enter(|stk| async {
let (ctx, opt, txn, fti) =
let (ctx, opt, fti) =
tx_fti(&ds, TransactionType::Read, &az, btree_order, false).await;
// Check the statistics
let statistics = fti.statistics(&txn).await.unwrap();
let statistics = fti.statistics(&ctx).await.unwrap();
assert_eq!(statistics.terms.keys_count, 7);
assert_eq!(statistics.postings.keys_count, 8);
assert_eq!(statistics.doc_ids.keys_count, 3);
assert_eq!(statistics.doc_lengths.keys_count, 3);
// Search & score
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "hello").await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "hello").await;
check_hits(
&txn,
&ctx,
hits,
scr,
vec![(&doc1, Some(-0.4859746)), (&doc2, Some(-0.4859746))],
)
.await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "world").await;
check_hits(&txn, hits, scr, vec![(&doc1, Some(0.4859746))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "world").await;
check_hits(&ctx, hits, scr, vec![(&doc1, Some(0.4859746))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "yellow").await;
check_hits(&txn, hits, scr, vec![(&doc2, Some(0.4859746))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "yellow").await;
check_hits(&ctx, hits, scr, vec![(&doc2, Some(0.4859746))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "foo").await;
check_hits(&txn, hits, scr, vec![(&doc3, Some(0.56902087))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "foo").await;
check_hits(&ctx, hits, scr, vec![(&doc3, Some(0.56902087))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "bar").await;
check_hits(&txn, hits, scr, vec![(&doc3, Some(0.56902087))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "bar").await;
check_hits(&ctx, hits, scr, vec![(&doc3, Some(0.56902087))]).await;
let (hits, _) = search(stk, &ctx, &opt, &txn, &fti, "dummy").await;
let (hits, _) = search(stk, &ctx, &opt, &fti, "dummy").await;
assert!(hits.is_none());
})
.finish()
@ -743,48 +720,48 @@ mod tests {
stack
.enter(|stk| async {
// Reindex one document
let (ctx, opt, txn, mut fti) =
let (ctx, opt, mut fti) =
tx_fti(&ds, TransactionType::Write, &az, btree_order, false).await;
fti.index_document(stk, &ctx, &opt, &txn, &doc3, vec![Value::from("nobar foo")])
fti.index_document(stk, &ctx, &opt, &doc3, vec![Value::from("nobar foo")])
.await
.unwrap();
finish(&txn, fti).await;
finish(&ctx, fti).await;
let (ctx, opt, txn, fti) =
let (ctx, opt, fti) =
tx_fti(&ds, TransactionType::Read, &az, btree_order, false).await;
// We can still find 'foo'
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "foo").await;
check_hits(&txn, hits, scr, vec![(&doc3, Some(0.56902087))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "foo").await;
check_hits(&ctx, hits, scr, vec![(&doc3, Some(0.56902087))]).await;
// We can't anymore find 'bar'
let (hits, _) = search(stk, &ctx, &opt, &txn, &fti, "bar").await;
let (hits, _) = search(stk, &ctx, &opt, &fti, "bar").await;
assert!(hits.is_none());
// We can now find 'nobar'
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "nobar").await;
check_hits(&txn, hits, scr, vec![(&doc3, Some(0.56902087))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "nobar").await;
check_hits(&ctx, hits, scr, vec![(&doc3, Some(0.56902087))]).await;
})
.finish()
.await;
{
// Remove documents
let (_, _, txn, mut fti) =
let (ctx, _, mut fti) =
tx_fti(&ds, TransactionType::Write, &az, btree_order, false).await;
fti.remove_document(&txn, &doc1).await.unwrap();
fti.remove_document(&txn, &doc2).await.unwrap();
fti.remove_document(&txn, &doc3).await.unwrap();
finish(&txn, fti).await;
fti.remove_document(&ctx, &doc1).await.unwrap();
fti.remove_document(&ctx, &doc2).await.unwrap();
fti.remove_document(&ctx, &doc3).await.unwrap();
finish(&ctx, fti).await;
}
stack
.enter(|stk| async {
let (ctx, opt, txn, fti) =
let (ctx, opt, fti) =
tx_fti(&ds, TransactionType::Read, &az, btree_order, false).await;
let (hits, _) = search(stk, &ctx, &opt, &txn, &fti, "hello").await;
let (hits, _) = search(stk, &ctx, &opt, &fti, "hello").await;
assert!(hits.is_none());
let (hits, _) = search(stk, &ctx, &opt, &txn, &fti, "foo").await;
let (hits, _) = search(stk, &ctx, &opt, &fti, "foo").await;
assert!(hits.is_none());
})
.finish()
@ -812,13 +789,12 @@ mod tests {
let btree_order = 5;
stack
.enter(|stk| async {
let (ctx, opt, txn, mut fti) =
let (ctx, opt, mut fti) =
tx_fti(&ds, TransactionType::Write, &az, btree_order, hl).await;
fti.index_document(
stk,
&ctx,
&opt,
&txn,
&doc1,
vec![Value::from("the quick brown fox jumped over the lazy dog")],
)
@ -828,7 +804,6 @@ mod tests {
stk,
&ctx,
&opt,
&txn,
&doc2,
vec![Value::from("the fast fox jumped over the lazy dog")],
)
@ -838,7 +813,6 @@ mod tests {
stk,
&ctx,
&opt,
&txn,
&doc3,
vec![Value::from("the dog sat there and did nothing")],
)
@ -848,31 +822,30 @@ mod tests {
stk,
&ctx,
&opt,
&txn,
&doc4,
vec![Value::from("the other animals sat there watching")],
)
.await
.unwrap();
finish(&txn, fti).await;
finish(&ctx, fti).await;
})
.finish()
.await;
stack
.enter(|stk| async {
let (ctx, opt, txn, fti) =
let (ctx, opt, fti) =
tx_fti(&ds, TransactionType::Read, &az, btree_order, hl).await;
let statistics = fti.statistics(&txn).await.unwrap();
let statistics = fti.statistics(&ctx).await.unwrap();
assert_eq!(statistics.terms.keys_count, 17);
assert_eq!(statistics.postings.keys_count, 28);
assert_eq!(statistics.doc_ids.keys_count, 4);
assert_eq!(statistics.doc_lengths.keys_count, 4);
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "the").await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "the").await;
check_hits(
&txn,
&ctx,
hits,
scr,
vec![
@ -884,9 +857,9 @@ mod tests {
)
.await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "dog").await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "dog").await;
check_hits(
&txn,
&ctx,
hits,
scr,
vec![
@ -897,25 +870,25 @@ mod tests {
)
.await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "fox").await;
check_hits(&txn, hits, scr, vec![(&doc1, Some(0.0)), (&doc2, Some(0.0))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "fox").await;
check_hits(&ctx, hits, scr, vec![(&doc1, Some(0.0)), (&doc2, Some(0.0))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "over").await;
check_hits(&txn, hits, scr, vec![(&doc1, Some(0.0)), (&doc2, Some(0.0))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "over").await;
check_hits(&ctx, hits, scr, vec![(&doc1, Some(0.0)), (&doc2, Some(0.0))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "lazy").await;
check_hits(&txn, hits, scr, vec![(&doc1, Some(0.0)), (&doc2, Some(0.0))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "lazy").await;
check_hits(&ctx, hits, scr, vec![(&doc1, Some(0.0)), (&doc2, Some(0.0))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "jumped").await;
check_hits(&txn, hits, scr, vec![(&doc1, Some(0.0)), (&doc2, Some(0.0))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "jumped").await;
check_hits(&ctx, hits, scr, vec![(&doc1, Some(0.0)), (&doc2, Some(0.0))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "nothing").await;
check_hits(&txn, hits, scr, vec![(&doc3, Some(0.87105393))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "nothing").await;
check_hits(&ctx, hits, scr, vec![(&doc3, Some(0.87105393))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &txn, &fti, "animals").await;
check_hits(&txn, hits, scr, vec![(&doc4, Some(0.92279965))]).await;
let (hits, scr) = search(stk, &ctx, &opt, &fti, "animals").await;
check_hits(&ctx, hits, scr, vec![(&doc4, Some(0.92279965))]).await;
let (hits, _) = search(stk, &ctx, &opt, &txn, &fti, "dummy").await;
let (hits, _) = search(stk, &ctx, &opt, &fti, "dummy").await;
assert!(hits.is_none());
})
.finish()
@ -970,11 +943,10 @@ mod tests {
rid: &Thing,
content: &Value,
) {
let (ctx, opt, txn, mut fti) =
tx_fti(ds, TransactionType::Write, az, btree_order, false).await;
fti.remove_document(&txn, rid).await.unwrap();
fti.index_document(stk, &ctx, &opt, &txn, rid, vec![content.clone()]).await.unwrap();
finish(&txn, fti).await;
let (ctx, opt, mut fti) = tx_fti(ds, TransactionType::Write, az, btree_order, false).await;
fti.remove_document(&ctx, rid).await.unwrap();
fti.index_document(stk, &ctx, &opt, rid, vec![content.clone()]).await.unwrap();
finish(&ctx, fti).await;
}
#[test(tokio::test)]
@ -991,33 +963,30 @@ mod tests {
for i in 0..5 {
debug!("Attempt {i}");
{
let (ctx, opt, txn, mut fti) =
tx_fti(&ds, TransactionType::Write, &az, 5, false).await;
let (ctx, opt, mut fti) = tx_fti(&ds, TransactionType::Write, &az, 5, false).await;
stack
.enter(|stk| {
fti.index_document(stk, &ctx, &opt, &txn, &doc, vec![content.clone()])
})
.enter(|stk| fti.index_document(stk, &ctx, &opt, &doc, vec![content.clone()]))
.finish()
.await
.unwrap();
finish(&txn, fti).await;
finish(&ctx, fti).await;
}
{
let (_, _, txn, fti) = tx_fti(&ds, TransactionType::Read, &az, 5, false).await;
let s = fti.statistics(&txn).await.unwrap();
let (ctx, _, fti) = tx_fti(&ds, TransactionType::Read, &az, 5, false).await;
let s = fti.statistics(&ctx).await.unwrap();
assert_eq!(s.terms.keys_count, 113);
}
{
let (_, _, txn, mut fti) = tx_fti(&ds, TransactionType::Write, &az, 5, false).await;
fti.remove_document(&txn, &doc).await.unwrap();
finish(&txn, fti).await;
let (ctx, _, mut fti) = tx_fti(&ds, TransactionType::Write, &az, 5, false).await;
fti.remove_document(&ctx, &doc).await.unwrap();
finish(&ctx, fti).await;
}
{
let (_, _, txn, fti) = tx_fti(&ds, TransactionType::Read, &az, 5, false).await;
let s = fti.statistics(&txn).await.unwrap();
let (ctx, _, fti) = tx_fti(&ds, TransactionType::Read, &az, 5, false).await;
let s = fti.statistics(&ctx).await.unwrap();
assert_eq!(s.terms.keys_count, 0);
}
}

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Iterable, Options, Transaction};
use crate::dbs::{Iterable, Options};
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::idx::docids::{DocId, DocIds};
@ -32,15 +32,13 @@ impl<'a> Default for HnswConditionChecker<'a> {
impl<'a> HnswConditionChecker<'a> {
pub(in crate::idx) fn new_cond(
ctx: &'a Context<'a>,
ctx: &'a Context<'_>,
opt: &'a Options,
txn: &'a Transaction,
cond: Arc<Cond>,
) -> Self {
Self::HnswCondition(HnswCondChecker {
ctx,
opt,
txn,
cond,
cache: Default::default(),
})
@ -83,28 +81,22 @@ impl<'a> HnswConditionChecker<'a> {
}
impl<'a> MTreeConditionChecker<'a> {
pub fn new_cond(
ctx: &'a Context<'_>,
opt: &'a Options,
txn: &'a Transaction,
cond: Arc<Cond>,
) -> Self {
pub fn new_cond(ctx: &'a Context<'_>, opt: &'a Options, cond: Arc<Cond>) -> Self {
if Cond(Value::Bool(true)).ne(cond.as_ref()) {
return Self::MTreeCondition(MTreeCondChecker {
ctx,
opt,
txn,
cond,
cache: Default::default(),
});
} else {
Self::new(txn)
Self::new(ctx)
}
}
pub fn new(txn: &'a Transaction) -> Self {
pub fn new(ctx: &'a Context<'a>) -> Self {
Self::MTree(MTreeChecker {
txn,
ctx,
})
}
@ -139,7 +131,7 @@ impl<'a> MTreeConditionChecker<'a> {
}
pub struct MTreeChecker<'a> {
txn: &'a Transaction,
ctx: &'a Context<'a>,
}
impl<'a> MTreeChecker<'a> {
@ -152,7 +144,7 @@ impl<'a> MTreeChecker<'a> {
return Ok(VecDeque::from([]));
}
let mut result = VecDeque::with_capacity(res.len());
let mut tx = self.txn.lock().await;
let mut tx = self.ctx.tx_lock().await;
for (doc_id, dist) in res {
if let Some(key) = doc_ids.get_doc_key(&mut tx, doc_id).await? {
result.push_back((key.into(), dist, None));
@ -190,12 +182,11 @@ impl CheckerCacheEntry {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
rid: Option<Thing>,
cond: &Cond,
) -> Result<Self, Error> {
if let Some(rid) = rid {
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
let val = Iterable::fetch_thing(&mut tx, opt, &rid).await?;
drop(tx);
if !val.is_none_or_null() {
@ -205,8 +196,7 @@ impl CheckerCacheEntry {
ir: None,
doc: Cow::Owned(val),
};
let truthy =
cond.compute(stk, ctx, opt, txn, Some(&cursor_doc)).await?.is_truthy();
let truthy = cond.compute(stk, ctx, opt, Some(&cursor_doc)).await?.is_truthy();
(cursor_doc.doc.into_owned(), truthy)
};
return Ok(CheckerCacheEntry {
@ -225,7 +215,6 @@ impl CheckerCacheEntry {
pub struct MTreeCondChecker<'a> {
ctx: &'a Context<'a>,
opt: &'a Options,
txn: &'a Transaction,
cond: Arc<Cond>,
cache: HashMap<DocId, CheckerCacheEntry>,
}
@ -240,18 +229,12 @@ impl<'a> MTreeCondChecker<'a> {
match self.cache.entry(doc_id) {
Entry::Occupied(e) => Ok(e.get().truthy),
Entry::Vacant(e) => {
let mut tx = self.txn.lock().await;
let mut tx = self.ctx.tx_lock().await;
let rid = doc_ids.get_doc_key(&mut tx, doc_id).await?.map(|k| k.into());
drop(tx);
let ent = CheckerCacheEntry::build(
stk,
self.ctx,
self.opt,
self.txn,
rid,
self.cond.as_ref(),
)
.await?;
let ent =
CheckerCacheEntry::build(stk, self.ctx, self.opt, rid, self.cond.as_ref())
.await?;
let truthy = ent.truthy;
e.insert(ent);
Ok(truthy)
@ -298,7 +281,6 @@ impl<'a> HnswChecker {
pub struct HnswCondChecker<'a> {
ctx: &'a Context<'a>,
opt: &'a Options,
txn: &'a Transaction,
cond: Arc<Cond>,
cache: HashMap<DocId, CheckerCacheEntry>,
}
@ -320,15 +302,9 @@ impl<'a> HnswCondChecker<'a> {
Entry::Occupied(e) => e.get().truthy,
Entry::Vacant(e) => {
let rid: Option<Thing> = docs.get_thing(doc_id).cloned();
let ent = CheckerCacheEntry::build(
stk,
self.ctx,
self.opt,
self.txn,
rid,
self.cond.as_ref(),
)
.await?;
let ent =
CheckerCacheEntry::build(stk, self.ctx, self.opt, rid, self.cond.as_ref())
.await?;
let truthy = ent.truthy;
e.insert(ent);
truthy

View file

@ -1,9 +1,10 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::idx::docids::DocIds;
use crate::idx::ft::analyzer::{Analyzer, TermsList, TermsSet};
use crate::idx::ft::highlighter::HighlightParams;
use crate::idx::ft::scorer::BM25Scorer;
use crate::idx::ft::termdocs::TermsDocs;
use crate::idx::ft::terms::Terms;
@ -105,7 +106,6 @@ impl InnerQueryExecutor {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
table: &Table,
im: IndexesMap,
knns: KnnExpressions,
@ -130,22 +130,19 @@ impl InnerQueryExecutor {
match &idx_def.index {
Index::Search(p) => {
let ft_entry = match ft_map.entry(ix_ref) {
Entry::Occupied(e) => {
FtEntry::new(stk, ctx, opt, txn, e.get(), io).await?
}
Entry::Occupied(e) => FtEntry::new(stk, ctx, opt, e.get(), io).await?,
Entry::Vacant(e) => {
let ikb = IndexKeyBase::new(opt, idx_def);
let ft = FtIndex::new(
ctx.get_index_stores(),
ctx,
opt,
txn,
p.az.as_str(),
ikb,
p,
TransactionType::Read,
)
.await?;
let fte = FtEntry::new(stk, ctx, opt, txn, &ft, io).await?;
let fte = FtEntry::new(stk, ctx, opt, &ft, io).await?;
e.insert(ft);
fte
}
@ -169,7 +166,6 @@ impl InnerQueryExecutor {
stk,
ctx,
opt,
txn,
e.get(),
a,
*k,
@ -179,7 +175,7 @@ impl InnerQueryExecutor {
}
Entry::Vacant(e) => {
let ikb = IndexKeyBase::new(opt, idx_def);
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
let mt = MTreeIndex::new(
ctx.get_index_stores(),
&mut tx,
@ -193,7 +189,6 @@ impl InnerQueryExecutor {
stk,
ctx,
opt,
txn,
&mt,
a,
*k,
@ -215,7 +210,6 @@ impl InnerQueryExecutor {
stk,
ctx,
opt,
txn,
e.get().clone(),
a,
*k,
@ -233,7 +227,6 @@ impl InnerQueryExecutor {
stk,
ctx,
opt,
txn,
hnsw.clone(),
a,
*k,
@ -279,13 +272,11 @@ impl InnerQueryExecutor {
}
impl QueryExecutor {
#[allow(clippy::too_many_arguments)]
pub(crate) async fn knn(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
thg: &Thing,
doc: Option<&CursorDoc<'_>>,
exp: &Expression,
@ -297,7 +288,7 @@ impl QueryExecutor {
Ok(Value::Bool(false))
} else {
if let Some((p, id, val, dist)) = self.0.knn_bruteforce_entries.get(exp) {
let v: Vec<Number> = id.compute(stk, ctx, opt, txn, doc).await?.try_into()?;
let v: Vec<Number> = id.compute(stk, ctx, opt, doc).await?.try_into()?;
let dist = dist.compute(&v, val.as_ref())?;
p.add(dist, thg).await;
}
@ -538,7 +529,6 @@ impl QueryExecutor {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
thg: &Thing,
exp: &Expression,
l: Value,
@ -547,10 +537,10 @@ impl QueryExecutor {
if let Some(ft) = self.0.exp_entries.get(exp) {
if let Some(ix_def) = self.get_index_def(ft.0.index_option.ix_ref()) {
if self.0.table.eq(&ix_def.what.0) {
return self.matches_with_doc_id(txn, thg, ft).await;
return self.matches_with_doc_id(ctx, thg, ft).await;
}
}
return self.matches_with_value(stk, ctx, opt, txn, ft, l, r).await;
return self.matches_with_value(stk, ctx, opt, ft, l, r).await;
}
// If no previous case were successful, we end up with a user error
@ -561,12 +551,12 @@ impl QueryExecutor {
async fn matches_with_doc_id(
&self,
txn: &Transaction,
ctx: &Context<'_>,
thg: &Thing,
ft: &FtEntry,
) -> Result<bool, Error> {
let doc_key: Key = thg.into();
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
let di = ft.0.doc_ids.read().await;
let doc_id = di.get_doc_id(&mut run, doc_key).await?;
drop(di);
@ -592,13 +582,11 @@ impl QueryExecutor {
Ok(false)
}
#[allow(clippy::too_many_arguments)]
async fn matches_with_value(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
ft: &FtEntry,
l: Value,
r: Value,
@ -615,7 +603,7 @@ impl QueryExecutor {
};
let terms = ft.0.terms.read().await;
// Extract the terms set from the record
let t = ft.0.analyzer.extract_indexing_terms(stk, ctx, opt, txn, &terms, v).await?;
let t = ft.0.analyzer.extract_indexing_terms(stk, ctx, opt, &terms, v).await?;
drop(terms);
Ok(ft.0.query_terms_set.is_subset(&t))
}
@ -637,27 +625,21 @@ impl QueryExecutor {
None
}
#[allow(clippy::too_many_arguments)]
pub(crate) async fn highlight(
&self,
txn: &Transaction,
ctx: &Context<'_>,
thg: &Thing,
prefix: Value,
suffix: Value,
match_ref: Value,
partial: bool,
hlp: HighlightParams,
doc: &Value,
) -> Result<Value, Error> {
if let Some((e, ft)) = self.get_ft_entry_and_index(&match_ref) {
let mut run = txn.lock().await;
if let Some((e, ft)) = self.get_ft_entry_and_index(hlp.match_ref()) {
let mut run = ctx.tx_lock().await;
let res = ft
.highlight(
&mut run,
thg,
&e.0.query_terms_list,
prefix,
suffix,
partial,
hlp,
e.0.index_option.id_ref(),
doc,
)
@ -670,13 +652,13 @@ impl QueryExecutor {
pub(crate) async fn offsets(
&self,
txn: &Transaction,
ctx: &Context<'_>,
thg: &Thing,
match_ref: Value,
partial: bool,
) -> Result<Value, Error> {
if let Some((e, ft)) = self.get_ft_entry_and_index(&match_ref) {
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
let res = ft.extract_offsets(&mut run, thg, &e.0.query_terms_list, partial).await;
drop(run);
return res;
@ -686,14 +668,14 @@ impl QueryExecutor {
pub(crate) async fn score(
&self,
txn: &Transaction,
ctx: &Context<'_>,
match_ref: &Value,
rid: &Thing,
ir: Option<&IteratorRecord>,
) -> Result<Value, Error> {
if let Some(e) = self.get_ft_entry(match_ref) {
if let Some(scorer) = &e.0.scorer {
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
let mut doc_id = if let Some(ir) = ir {
ir.doc_id()
} else {
@ -738,14 +720,13 @@ impl FtEntry {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
ft: &FtIndex,
io: IndexOption,
) -> Result<Option<Self>, Error> {
if let Matches(qs, _) = io.op() {
let (terms_list, terms_set) =
ft.extract_querying_terms(stk, ctx, opt, txn, qs.to_owned()).await?;
let mut tx = txn.lock().await;
ft.extract_querying_terms(stk, ctx, opt, qs.to_owned()).await?;
let mut tx = ctx.tx_lock().await;
let terms_docs = Arc::new(ft.get_terms_docs(&mut tx, &terms_list).await?);
drop(tx);
Ok(Some(Self(Arc::new(Inner {
@ -770,23 +751,21 @@ pub(super) struct MtEntry {
}
impl MtEntry {
#[allow(clippy::too_many_arguments)]
async fn new(
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
mt: &MTreeIndex,
o: &[Number],
k: u32,
cond: Option<Arc<Cond>>,
) -> Result<Self, Error> {
let cond_checker = if let Some(cond) = cond {
MTreeConditionChecker::new_cond(ctx, opt, txn, cond)
MTreeConditionChecker::new_cond(ctx, opt, cond)
} else {
MTreeConditionChecker::new(txn)
MTreeConditionChecker::new(ctx)
};
let res = mt.knn_search(stk, txn, o, k as usize, cond_checker).await?;
let res = mt.knn_search(stk, ctx, o, k as usize, cond_checker).await?;
Ok(Self {
res,
})
@ -804,7 +783,6 @@ impl HnswEntry {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
h: SharedHnswIndex,
v: &[Number],
n: u32,
@ -812,7 +790,7 @@ impl HnswEntry {
cond: Option<Arc<Cond>>,
) -> Result<Self, Error> {
let cond_checker = if let Some(cond) = cond {
HnswConditionChecker::new_cond(ctx, opt, txn, cond)
HnswConditionChecker::new_cond(ctx, opt, cond)
} else {
HnswConditionChecker::default()
};

View file

@ -7,7 +7,7 @@ pub(in crate::idx) mod rewriter;
pub(in crate::idx) mod tree;
use crate::ctx::Context;
use crate::dbs::{Iterable, Iterator, Options, Transaction};
use crate::dbs::{Iterable, Iterator, Options};
use crate::err::Error;
use crate::idx::planner::executor::{InnerQueryExecutor, IteratorEntry, QueryExecutor};
use crate::idx::planner::iterators::IteratorRef;
@ -50,20 +50,18 @@ impl<'a> QueryPlanner<'a> {
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
txn: &Transaction,
t: Table,
it: &mut Iterator,
) -> Result<(), Error> {
let mut is_table_iterator = false;
let mut is_knn = false;
match Tree::build(stk, ctx, self.opt, txn, &t, self.cond, self.with).await? {
match Tree::build(stk, ctx, self.opt, &t, self.cond, self.with).await? {
Some(tree) => {
is_knn = is_knn || !tree.knn_expressions.is_empty();
let mut exe = InnerQueryExecutor::new(
stk,
ctx,
self.opt,
txn,
&t,
tree.index_map,
tree.knn_expressions,

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::err::Error;
use crate::idx::planner::executor::{
KnnBruteForceExpression, KnnBruteForceExpressions, KnnExpressions,
@ -32,12 +32,11 @@ impl Tree {
stk: &mut Stk,
ctx: &'a Context<'_>,
opt: &'a Options,
txn: &'a Transaction,
table: &'a Table,
cond: &'a Option<Cond>,
with: &'a Option<With>,
) -> Result<Option<Self>, Error> {
let mut b = TreeBuilder::new(ctx, opt, txn, table, with);
let mut b = TreeBuilder::new(ctx, opt, table, with);
if let Some(cond) = cond {
let root = b.eval_value(stk, 0, &cond.0).await?;
let knn_condition = if b.knn_expressions.is_empty() {
@ -62,7 +61,6 @@ impl Tree {
struct TreeBuilder<'a> {
ctx: &'a Context<'a>,
opt: &'a Options,
txn: &'a Transaction,
table: &'a Table,
with: &'a Option<With>,
schemas: HashMap<Table, SchemaCache>,
@ -90,7 +88,6 @@ impl<'a> TreeBuilder<'a> {
fn new(
ctx: &'a Context<'_>,
opt: &'a Options,
txn: &'a Transaction,
table: &'a Table,
with: &'a Option<With>,
) -> Self {
@ -101,7 +98,6 @@ impl<'a> TreeBuilder<'a> {
Self {
ctx,
opt,
txn,
table,
with,
schemas: Default::default(),
@ -159,7 +155,7 @@ impl<'a> TreeBuilder<'a> {
async fn compute(&self, stk: &mut Stk, v: &Value, n: Node) -> Result<Node, Error> {
Ok(if n == Node::Computable {
match v.compute(stk, self.ctx, self.opt, self.txn, None).await {
match v.compute(stk, self.ctx, self.opt, None).await {
Ok(v) => Node::Computed(Arc::new(v)),
Err(_) => Node::Unsupported(format!("Unsupported value: {}", v)),
}
@ -171,7 +167,7 @@ impl<'a> TreeBuilder<'a> {
async fn eval_array(&mut self, stk: &mut Stk, a: &Array) -> Result<Node, Error> {
let mut values = Vec::with_capacity(a.len());
for v in &a.0 {
values.push(stk.run(|stk| v.compute(stk, self.ctx, self.opt, self.txn, None)).await?);
values.push(stk.run(|stk| v.compute(stk, self.ctx, self.opt, None)).await?);
}
Ok(Node::Computed(Arc::new(Value::Array(Array::from(values)))))
}
@ -190,7 +186,7 @@ impl<'a> TreeBuilder<'a> {
// Compute the idiom value if it is a param
if let Some(Part::Start(x)) = i.0.first() {
if x.is_param() {
let v = stk.run(|stk| i.compute(stk, self.ctx, self.opt, self.txn, None)).await?;
let v = stk.run(|stk| i.compute(stk, self.ctx, self.opt, None)).await?;
return stk.run(|stk| self.eval_value(stk, group, &v)).await;
}
}
@ -202,7 +198,7 @@ impl<'a> TreeBuilder<'a> {
}
async fn resolve_idiom(&mut self, i: &Idiom) -> Result<Node, Error> {
let mut tx = self.txn.lock().await;
let mut tx = self.ctx.tx_lock().await;
self.lazy_load_schema_resolver(&mut tx, self.table).await?;
// Try to detect if it matches an index

View file

@ -1,4 +1,4 @@
use crate::dbs;
use crate::ctx::Context;
use hashbrown::hash_map::Entry;
use hashbrown::{HashMap, HashSet};
use reblessive::tree::Stk;
@ -39,7 +39,7 @@ pub struct MTreeIndex {
}
struct MTreeSearchContext<'a> {
txn: &'a dbs::Transaction,
ctx: &'a Context<'a>,
pt: SharedVector,
k: usize,
store: &'a MTreeStore,
@ -109,7 +109,7 @@ impl MTreeIndex {
pub async fn knn_search(
&self,
stk: &mut Stk,
txn: &dbs::Transaction,
ctx: &Context<'_>,
v: &[Number],
k: usize,
mut chk: MTreeConditionChecker<'_>,
@ -119,7 +119,7 @@ impl MTreeIndex {
vector.check_dimension(self.dim)?;
// Build the search context
let search = MTreeSearchContext {
txn,
ctx,
pt: vector.into(),
k,
store: &self.store,
@ -219,7 +219,7 @@ impl MTree {
let mut visited_nodes = HashMap::new();
while let Some(e) = queue.pop() {
let id = e.id();
let node = search.store.get_node_txn(search.txn, id).await?;
let node = search.store.get_node_txn(search.ctx, id).await?;
#[cfg(debug_assertions)]
{
debug!("Visit node id: {}", id);
@ -1477,7 +1477,7 @@ mod tests {
use std::collections::VecDeque;
use std::sync::Arc;
use crate::dbs;
use crate::ctx::Context;
use crate::err::Error;
use test_log::test;
@ -1498,13 +1498,14 @@ mod tests {
t: &MTree,
tt: TransactionType,
cache_size: usize,
) -> (dbs::Transaction, TreeStore<MTreeNode>) {
) -> (Context<'a>, TreeStore<MTreeNode>) {
let st = ds
.index_store()
.get_store_mtree(TreeNodeProvider::Debug, t.state.generation, tt, cache_size)
.await;
let tx = Arc::new(Mutex::new(ds.transaction(tt, Optimistic).await.unwrap()));
(tx, st)
let ctx = Context::default().set_transaction(tx);
(ctx, st)
}
async fn finish_operation(
@ -1538,8 +1539,8 @@ mod tests {
let mut c = 0;
for (doc_id, obj) in collection.to_vec_ref() {
{
let (txn, mut st) = new_operation(ds, t, TransactionType::Write, cache_size).await;
let mut tx = txn.lock().await;
let (ctx, mut st) = new_operation(ds, t, TransactionType::Write, cache_size).await;
let mut tx = ctx.tx_lock().await;
t.insert(stk, &mut tx, &mut st, obj.clone(), *doc_id).await?;
finish_operation(ds, t, &mut tx, st, true).await?;
drop(tx);
@ -1547,8 +1548,8 @@ mod tests {
}
c += 1;
{
let (txn, mut st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let mut tx = txn.lock().await;
let (ctx, mut st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let mut tx = ctx.tx_lock().await;
let p = check_tree_properties(&mut tx, &mut st, t).await?;
drop(tx);
assert_eq!(p.doc_count, c);
@ -1566,8 +1567,8 @@ mod tests {
) -> Result<HashMap<DocId, SharedVector>, Error> {
let mut map = HashMap::with_capacity(collection.len());
{
let (txn, mut st) = new_operation(ds, t, TransactionType::Write, cache_size).await;
let mut tx = txn.lock().await;
let (ctx, mut st) = new_operation(ds, t, TransactionType::Write, cache_size).await;
let mut tx = ctx.tx_lock().await;
for (doc_id, obj) in collection.to_vec_ref() {
t.insert(stk, &mut tx, &mut st, obj.clone(), *doc_id).await?;
map.insert(*doc_id, obj.clone());
@ -1576,8 +1577,8 @@ mod tests {
drop(tx);
}
{
let (txn, mut st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let mut tx = txn.lock().await;
let (ctx, mut st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let mut tx = ctx.tx_lock().await;
check_tree_properties(&mut tx, &mut st, t).await?;
drop(tx);
}
@ -1596,8 +1597,8 @@ mod tests {
for (doc_id, obj) in collection.to_vec_ref() {
let deleted = {
debug!("### Remove {} {:?}", doc_id, obj);
let (txn, mut st) = new_operation(ds, t, TransactionType::Write, cache_size).await;
let mut tx = txn.lock().await;
let (ctx, mut st) = new_operation(ds, t, TransactionType::Write, cache_size).await;
let mut tx = ctx.tx_lock().await;
let deleted = t.delete(stk, &mut tx, &mut st, obj.clone(), *doc_id).await?;
finish_operation(ds, t, &mut tx, st, true).await?;
drop(tx);
@ -1605,10 +1606,10 @@ mod tests {
};
all_deleted = all_deleted && deleted;
if deleted {
let (txn, st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let mut chk = MTreeConditionChecker::new(&txn);
let (ctx, st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let mut chk = MTreeConditionChecker::new(&ctx);
let search = MTreeSearchContext {
txn: &txn,
ctx: &ctx,
pt: obj.clone(),
k: 1,
store: &st,
@ -1625,16 +1626,16 @@ mod tests {
warn!("Delete failed: {} {:?}", doc_id, obj);
}
{
let (txn, mut st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let mut tx = txn.lock().await;
let (ctx, mut st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let mut tx = ctx.tx_lock().await;
check_tree_properties(&mut tx, &mut st, t).await?;
drop(tx);
}
}
if all_deleted {
let (txn, mut st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let mut tx = txn.lock().await;
let (ctx, mut st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let mut tx = ctx.tx_lock().await;
check_tree_properties(&mut tx, &mut st, t).await?.check(0, 0, None, None, 0, 0);
drop(tx);
}
@ -1649,13 +1650,13 @@ mod tests {
collection: &TestCollection,
cache_size: usize,
) -> Result<(), Error> {
let (txn, mut st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let (ctx, mut st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let max_knn = 20.max(collection.len());
for (doc_id, obj) in collection.to_vec_ref() {
for knn in 1..max_knn {
let mut chk = MTreeConditionChecker::new(&txn);
let mut chk = MTreeConditionChecker::new(&ctx);
let search = MTreeSearchContext {
txn: &txn,
ctx: &ctx,
pt: obj.clone(),
k: knn,
store: &st,
@ -1676,7 +1677,7 @@ mod tests {
if expected_len != res.docs.len() {
#[cfg(debug_assertions)]
debug!("{:?}", res.visited_nodes);
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
check_tree_properties(&mut tx, &mut st, t).await?;
drop(tx);
}
@ -1701,11 +1702,11 @@ mod tests {
map: &HashMap<DocId, SharedVector>,
cache_size: usize,
) -> Result<(), Error> {
let (txn, st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
let (ctx, st) = new_operation(ds, t, TransactionType::Read, cache_size).await;
for obj in map.values() {
let mut chk = MTreeConditionChecker::new(&txn);
let mut chk = MTreeConditionChecker::new(&ctx);
let search = MTreeSearchContext {
txn: &txn,
ctx: &ctx,
pt: obj.clone(),
k: map.len(),
store: &st,
@ -1758,8 +1759,8 @@ mod tests {
let mut t = MTree::new(MState::new(*capacity), distance.clone());
let (txn, _st) = new_operation(&ds, &t, TransactionType::Read, cache_size).await;
let mut tx = txn.lock().await;
let (ctx, _st) = new_operation(&ds, &t, TransactionType::Read, cache_size).await;
let mut tx = ctx.tx_lock().await;
let doc_ids = DocIds::new(
ds.index_store(),
&mut tx,

View file

@ -3,7 +3,7 @@ pub(crate) mod hnsw;
mod lru;
pub(crate) mod tree;
use crate::dbs;
use crate::ctx::Context;
use crate::dbs::Options;
use crate::err::Error;
use crate::idx::trees::bkeys::{FstKeys, TrieKeys};
@ -69,12 +69,12 @@ where
pub(in crate::idx) async fn get_node_txn(
&self,
txn: &dbs::Transaction,
ctx: &Context<'_>,
node_id: NodeId,
) -> Result<Arc<StoredNode<N>>, Error> {
match self {
Self::Read(r) => {
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
let n = r.get_node(&mut tx, node_id).await;
drop(tx);
n

View file

@ -484,9 +484,9 @@ impl Datastore {
info!("Credentials were provided, and no root users were found. The root user '{}' will be created", username);
// Create and save a new root users
let stm = DefineUserStatement::from((Base::Root, username, password));
let ctx = Context::default();
let ctx = Context::default().set_transaction(txn.clone());
let opt = Options::new().with_auth(Arc::new(Auth::for_root(Role::Owner)));
let _ = stm.compute(&ctx, &opt, &txn, None).await?;
let _ = stm.compute(&ctx, &opt, None).await?;
// We added a new user, so commit the transaction
txn.lock().await.commit().await?;
// Everything ok
@ -1260,7 +1260,7 @@ impl Datastore {
// Start a new transaction
let txn = self.transaction(val.writeable().into(), Optimistic).await?.enclose();
// Compute the value
let res = stack.enter(|stk| val.compute(stk, &ctx, &opt, &txn, None)).finish().await;
let res = stack.enter(|stk| val.compute(stk, &ctx, &opt, None)).finish().await;
// Store any data
match (res.is_ok(), val.writeable()) {
// If the compute was successful, then commit if writeable
@ -1334,8 +1334,10 @@ impl Datastore {
let ctx = vars.attach(ctx)?;
// Start a new transaction
let txn = self.transaction(val.writeable().into(), Optimistic).await?.enclose();
let ctx = ctx.set_transaction(txn.clone());
// Compute the value
let res = stack.enter(|stk| val.compute(stk, &ctx, &opt, &txn, None)).finish().await;
let res = stack.enter(|stk| val.compute(stk, &ctx, &opt, None)).finish().await;
// Store any data
match (res.is_ok(), val.writeable()) {
// If the compute was successful, then commit if writeable
@ -1463,10 +1465,10 @@ mod test {
ctx.add_capabilities(dbs.capabilities.clone());
// Start a new transaction
let txn = dbs.transaction(val.writeable().into(), Optimistic).await?.enclose();
let ctx = ctx.set_transaction(txn);
// Compute the value
let mut stack = reblessive::tree::TreeStack::new();
let res =
stack.enter(|stk| val.compute(stk, &ctx, &opt, &txn, None)).finish().await.unwrap();
let res = stack.enter(|stk| val.compute(stk, &ctx, &opt, None)).finish().await.unwrap();
assert_eq!(res, Value::Number(Number::Int(2)));
Ok(())
}

View file

@ -209,7 +209,7 @@ mod test_check_lqs_and_send_notifications {
use crate::fflags::FFLAGS;
use crate::iam::{Auth, Role};
use crate::kvs::lq_v2_doc::construct_document;
use crate::kvs::{Datastore, LockType, TransactionType};
use crate::kvs::Datastore;
use crate::sql::paths::{OBJ_PATH_ACCESS, OBJ_PATH_AUTH, OBJ_PATH_TOKEN};
use crate::sql::statements::{CreateStatement, DeleteStatement, LiveStatement};
use crate::sql::{Fields, Object, Strand, Table, Thing, Uuid, Value, Values};
@ -217,7 +217,6 @@ mod test_check_lqs_and_send_notifications {
const SETUP: Lazy<Arc<TestSuite>> = Lazy::new(|| Arc::new(block_on(setup_test_suite_init())));
struct TestSuite {
ds: Datastore,
ns: String,
db: String,
tb: String,
@ -249,7 +248,6 @@ mod test_check_lqs_and_send_notifications {
.for_each(drop);
TestSuite {
ds,
ns: ns.to_string(),
db: db.to_string(),
tb: tb.to_string(),
@ -265,12 +263,6 @@ mod test_check_lqs_and_send_notifications {
// Setup channels used for listening to LQs
let (sender, receiver) = channel::unbounded();
let opt = a_usable_options(&sender);
let tx = SETUP
.ds
.transaction(TransactionType::Write, LockType::Optimistic)
.await
.unwrap()
.enclose();
// WHEN:
// Construct document we are validating
@ -289,7 +281,6 @@ mod test_check_lqs_and_send_notifications {
stk,
&opt,
&Statement::Create(&executed_statement),
&tx,
&[&live_statement],
&sender,
)
@ -309,7 +300,6 @@ mod test_check_lqs_and_send_notifications {
notification
);
assert!(receiver.try_recv().is_err());
tx.lock().await.cancel().await.unwrap();
}
#[test_log::test(tokio::test)]
@ -321,12 +311,6 @@ mod test_check_lqs_and_send_notifications {
// Setup channels used for listening to LQs
let (sender, receiver) = channel::unbounded();
let opt = a_usable_options(&sender);
let tx = SETUP
.ds
.transaction(TransactionType::Write, LockType::Optimistic)
.await
.unwrap()
.enclose();
// WHEN:
// Construct document we are validating
@ -345,7 +329,6 @@ mod test_check_lqs_and_send_notifications {
stk,
&opt,
&Statement::Delete(&executed_statement),
&tx,
&[&live_statement],
&sender,
)
@ -367,7 +350,6 @@ mod test_check_lqs_and_send_notifications {
notification
);
assert!(receiver.try_recv().is_err());
tx.lock().await.cancel().await.unwrap();
}
// Live queries will have authentication info associated with them

View file

@ -11,7 +11,6 @@ use crate::kvs::TransactionType::Read;
use crate::kvs::{Datastore, Transaction};
use crate::sql::statements::show::ShowSince;
use crate::vs::conv;
use futures::lock::Mutex;
use reblessive::tree::Stk;
use std::collections::BTreeMap;
use std::sync::Arc;
@ -56,7 +55,6 @@ pub async fn process_lq_notifications(
let lq_pairs = ds.lq_cf_store.read().await.live_queries_for_selector(&selector);
// Find relevant changes
let tx = ds.transaction(Read, Optimistic).await?.enclose();
#[cfg(debug_assertions)]
trace!("There are {} change sets", change_sets.len());
#[cfg(debug_assertions)]
@ -70,8 +68,7 @@ pub async fn process_lq_notifications(
.join("\n")
);
for change_set in change_sets {
process_change_set_for_notifications(ds, stk, tx.clone(), opt, change_set, &lq_pairs)
.await?;
process_change_set_for_notifications(ds, stk, opt, change_set, &lq_pairs).await?;
}
}
trace!("Finished process lq successfully");
@ -135,7 +132,6 @@ async fn populate_relevant_changesets(
async fn process_change_set_for_notifications(
ds: &Datastore,
stk: &mut Stk,
tx: Arc<Mutex<Transaction>>,
opt: &Options,
change_set: ChangeSet,
lq_pairs: &[(LqIndexKey, LqIndexValue)],
@ -171,7 +167,6 @@ async fn process_change_set_for_notifications(
stk,
opt,
&Statement::Live(&lq_value.stm),
&tx,
[&lq_value.stm].as_slice(),
&local_notification_channel_sender,
)

View file

@ -106,9 +106,10 @@ async fn expired_nodes_get_live_queries_archived() {
.with_id(old_node);
let opt = Options::new_with_sender(&opt, sender);
let tx = Arc::new(Mutex::new(test.db.transaction(Write, Optimistic).await.unwrap()));
let ctx = ctx.set_transaction(tx);
let res = {
let mut stack = reblessive::tree::TreeStack::new();
stack.enter(|stk| lq.compute(stk, &ctx, &opt, &tx, None)).finish().await.unwrap()
stack.enter(|stk| lq.compute(stk, &ctx, &opt, None)).finish().await.unwrap()
};
match res {
Value::Uuid(_) => {}
@ -116,7 +117,7 @@ async fn expired_nodes_get_live_queries_archived() {
panic!("Not a uuid: {:?}", res);
}
}
tx.lock().await.commit().await.unwrap();
ctx.tx_lock().await.commit().await.unwrap();
// Set up second node at a later timestamp
let new_node = Uuid::parse_str("04da7d4c-0086-4358-8318-49f0bb168fa7").unwrap();
@ -170,6 +171,7 @@ async fn single_live_queries_are_garbage_collected() {
// We set up 2 live queries, one of which we want to garbage collect
trace!("Setting up live queries");
let tx = Arc::new(Mutex::new(test.db.transaction(Write, Optimistic).await.unwrap()));
let ctx = ctx.set_transaction(tx);
let live_query_to_delete = Uuid::parse_str("8aed07c4-9683-480e-b1e4-f0db8b331530").unwrap();
let live_st = LiveStatement {
id: sql::Uuid(live_query_to_delete),
@ -183,7 +185,7 @@ async fn single_live_queries_are_garbage_collected() {
auth: Some(Auth::for_root(Role::Owner)),
};
stack
.enter(|stk| live_st.compute(stk, &ctx, &options, &tx, None))
.enter(|stk| live_st.compute(stk, &ctx, &options, None))
.finish()
.await
.map_err(|e| format!("Error computing live statement: {:?} {:?}", live_st, e))
@ -201,12 +203,12 @@ async fn single_live_queries_are_garbage_collected() {
auth: Some(Auth::for_root(Role::Owner)),
};
stack
.enter(|stk| live_st.compute(stk, &ctx, &options, &tx, None))
.enter(|stk| live_st.compute(stk, &ctx, &options, None))
.finish()
.await
.map_err(|e| format!("Error computing live statement: {:?} {:?}", live_st, e))
.unwrap();
tx.lock().await.commit().await.unwrap();
ctx.tx_lock().await.commit().await.unwrap();
// Subject: Perform the action we are testing
trace!("Garbage collecting dead sessions");
@ -260,6 +262,7 @@ async fn bootstrap_does_not_error_on_missing_live_queries() {
// We set up 2 live queries, one of which we want to garbage collect
trace!("Setting up live queries");
let tx = Arc::new(Mutex::new(test.db.transaction(Write, Optimistic).await.unwrap()));
let ctx = ctx.set_transaction(tx);
let live_query_to_corrupt = Uuid::parse_str("d4cee7ce-5c78-4a30-9fa9-2444d58029f6").unwrap();
let live_st = LiveStatement {
id: sql::Uuid(live_query_to_corrupt),
@ -273,7 +276,7 @@ async fn bootstrap_does_not_error_on_missing_live_queries() {
auth: Some(Auth::for_root(Role::Owner)),
};
stack
.enter(|stk| live_st.compute(stk, &ctx, &options, &tx, None))
.enter(|stk| live_st.compute(stk, &ctx, &options, None))
.finish()
.await
.map_err(|e| format!("Error computing live statement: {:?} {:?}", live_st, e))
@ -281,8 +284,8 @@ async fn bootstrap_does_not_error_on_missing_live_queries() {
// Now we corrupt the live query entry by leaving the node entry in but removing the table entry
let key = crate::key::table::lq::new(namespace, database, table, live_query_to_corrupt);
tx.lock().await.del(key).await.unwrap();
tx.lock().await.commit().await.unwrap();
ctx.tx_lock().await.del(key).await.unwrap();
ctx.tx_lock().await.commit().await.unwrap();
// Subject: Perform the action we are testing
trace!("Bootstrapping");

View file

@ -28,6 +28,7 @@ use crate::dbs::node::ClusterMembership;
use crate::dbs::node::Timestamp;
use crate::err::Error;
use crate::idg::u32::U32;
#[cfg(debug_assertions)]
use crate::key::debug::sprint_key;
use crate::key::error::KeyCategory;
use crate::key::key_req::KeyRequirements;

View file

@ -5,7 +5,8 @@ extern crate tracing;
mod mac;
mod cf;
mod ctx;
#[doc(hidden)]
pub mod ctx;
mod doc;
mod exe;
mod fnc;

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::{
@ -137,12 +137,11 @@ impl Array {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
let mut x = Self::with_capacity(self.len());
for v in self.iter() {
match v.compute(stk, ctx, opt, txn, doc).await {
match v.compute(stk, ctx, opt, doc).await {
Ok(v) => x.push(v),
Err(e) => return Err(e),
};

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::fmt::{is_pretty, pretty_indent, Fmt, Pretty};
@ -51,7 +51,6 @@ impl Block {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Duplicate context
@ -60,65 +59,65 @@ impl Block {
for (i, v) in self.iter().enumerate() {
match v {
Entry::Set(v) => {
let val = v.compute(stk, &ctx, opt, txn, doc).await?;
let val = v.compute(stk, &ctx, opt, doc).await?;
ctx.add_value(v.name.to_owned(), val);
}
Entry::Throw(v) => {
// Always errors immediately
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Break(v) => {
// Always errors immediately
v.compute(&ctx, opt, txn, doc).await?;
v.compute(&ctx, opt, doc).await?;
}
Entry::Continue(v) => {
// Always errors immediately
v.compute(&ctx, opt, txn, doc).await?;
v.compute(&ctx, opt, doc).await?;
}
Entry::Foreach(v) => {
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Ifelse(v) => {
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Select(v) => {
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Create(v) => {
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Update(v) => {
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Delete(v) => {
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Relate(v) => {
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Insert(v) => {
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Define(v) => {
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Rebuild(v) => {
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
Entry::Remove(v) => {
v.compute(&ctx, opt, txn, doc).await?;
v.compute(&ctx, opt, doc).await?;
}
Entry::Output(v) => {
// Return the RETURN value
return v.compute(stk, &ctx, opt, txn, doc).await;
return v.compute(stk, &ctx, opt, doc).await;
}
Entry::Value(v) => {
if i == self.len() - 1 {
// If the last entry then return the value
return v.compute(stk, &ctx, opt, txn, doc).await;
return v.compute(stk, &ctx, opt, doc).await;
} else {
// Otherwise just process the value
v.compute(stk, &ctx, opt, txn, doc).await?;
v.compute(stk, &ctx, opt, doc).await?;
}
}
}

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::{Idiom, Kind, Value};
@ -39,11 +39,10 @@ impl Cast {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Compute the value to be cast and convert it
stk.run(|stk| self.1.compute(stk, ctx, opt, txn, doc)).await?.convert_to(&self.0)
stk.run(|stk| self.1.compute(stk, ctx, opt, doc)).await?.convert_to(&self.0)
}
}

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::value::Value;
@ -81,7 +81,6 @@ impl Constant {
&self,
_ctx: &Context<'_>,
_opt: &Options,
_txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
Ok(match self.value() {

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::err::Error;
use crate::sql::fmt::Fmt;
use crate::sql::idiom::Idiom;
@ -40,28 +40,27 @@ impl Data {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
) -> Result<Option<Value>, Error> {
match self {
Self::MergeExpression(v) => match v {
Value::Param(v) => Ok(v.compute(stk, ctx, opt, txn, None).await?.rid().some()),
Value::Param(v) => Ok(v.compute(stk, ctx, opt, None).await?.rid().some()),
Value::Object(_) => Ok(v.rid().some()),
_ => Ok(None),
},
Self::ReplaceExpression(v) => match v {
Value::Param(v) => Ok(v.compute(stk, ctx, opt, txn, None).await?.rid().some()),
Value::Param(v) => Ok(v.compute(stk, ctx, opt, None).await?.rid().some()),
Value::Object(_) => Ok(v.rid().some()),
_ => Ok(None),
},
Self::ContentExpression(v) => match v {
Value::Param(v) => Ok(v.compute(stk, ctx, opt, txn, None).await?.rid().some()),
Value::Param(v) => Ok(v.compute(stk, ctx, opt, None).await?.rid().some()),
Value::Object(_) => Ok(v.rid().some()),
_ => Ok(None),
},
Self::SetExpression(v) => match v.iter().find(|f| f.0.is_id()) {
Some((_, _, v)) => {
// This SET expression has an 'id' field
Ok(v.compute(stk, ctx, opt, txn, None).await?.some())
Ok(v.compute(stk, ctx, opt, None).await?.some())
}
// This SET expression had no 'id' field
_ => Ok(None),

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::fnc;
@ -102,7 +102,6 @@ impl Expression {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
let (l, o, r) = match self {
@ -110,7 +109,7 @@ impl Expression {
o,
v,
} => {
let operand = v.compute(stk, ctx, opt, txn, doc).await?;
let operand = v.compute(stk, ctx, opt, doc).await?;
return match o {
Operator::Neg => fnc::operate::neg(operand),
// TODO: Check if it is a number?
@ -126,7 +125,7 @@ impl Expression {
} => (l, o, r),
};
let l = l.compute(stk, ctx, opt, txn, doc).await?;
let l = l.compute(stk, ctx, opt, doc).await?;
match o {
Operator::Or => {
if l.is_truthy() {
@ -150,7 +149,7 @@ impl Expression {
}
_ => {} // Continue
}
let r = r.compute(stk, ctx, opt, txn, doc).await?;
let r = r.compute(stk, ctx, opt, doc).await?;
match o {
Operator::Or => fnc::operate::or(l, r),
Operator::And => fnc::operate::and(l, r),
@ -187,11 +186,9 @@ impl Expression {
Operator::NoneInside => fnc::operate::inside_none(&l, &r),
Operator::Outside => fnc::operate::outside(&l, &r),
Operator::Intersects => fnc::operate::intersects(&l, &r),
Operator::Matches(_) => {
fnc::operate::matches(stk, ctx, opt, txn, doc, self, l, r).await
}
Operator::Matches(_) => fnc::operate::matches(stk, ctx, opt, doc, self, l, r).await,
Operator::Knn(_, _) | Operator::Ann(_, _) => {
fnc::operate::knn(stk, ctx, opt, txn, doc, self).await
fnc::operate::knn(stk, ctx, opt, doc, self).await
}
_ => unreachable!(),
}

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::statements::info::InfoStructure;
@ -79,15 +79,14 @@ impl Fields {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
group: bool,
) -> Result<Value, Error> {
if let Some(doc) = doc {
self.compute_value(stk, ctx, opt, txn, doc, group).await
self.compute_value(stk, ctx, opt, doc, group).await
} else {
let doc = (&Value::None).into();
self.compute_value(stk, ctx, opt, txn, &doc, group).await
self.compute_value(stk, ctx, opt, &doc, group).await
}
}
@ -96,7 +95,6 @@ impl Fields {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: &CursorDoc<'_>,
group: bool,
) -> Result<Value, Error> {
@ -104,7 +102,7 @@ impl Fields {
let opt = &opt.new_with_futures(true);
// Process the desired output
let mut out = match self.is_all() {
true => doc.doc.compute(stk, ctx, opt, txn, Some(doc)).await?,
true => doc.doc.compute(stk, ctx, opt, Some(doc)).await?,
false => Value::base(),
};
for v in self.other() {
@ -123,13 +121,13 @@ impl Fields {
Value::Function(f) if group && f.is_aggregate() => {
let x = match f.args().len() {
// If no function arguments, then compute the result
0 => f.compute(stk, ctx, opt, txn, Some(doc)).await?,
0 => f.compute(stk, ctx, opt, Some(doc)).await?,
// If arguments, then pass the first value through
_ => f.args()[0].compute(stk, ctx, opt, txn, Some(doc)).await?,
_ => f.args()[0].compute(stk, ctx, opt, Some(doc)).await?,
};
// Check if this is a single VALUE field expression
match self.single().is_some() {
false => out.set(stk, ctx, opt, txn, name.as_ref(), x).await?,
false => out.set(stk, ctx, opt, name.as_ref(), x).await?,
true => out = x,
}
}
@ -146,9 +144,9 @@ impl Fields {
};
// Continue fetching the next idiom part
let x = x
.get(stk, ctx, opt, txn, Some(doc), v)
.get(stk, ctx, opt, Some(doc), v)
.await?
.compute(stk, ctx, opt, txn, Some(doc))
.compute(stk, ctx, opt, Some(doc))
.await?
.flatten();
// Add the result to the temporary store
@ -160,13 +158,13 @@ impl Fields {
// This is an alias expression part
Some(a) => {
if let Some(i) = alias {
out.set(stk, ctx, opt, txn, i, x.clone()).await?;
out.set(stk, ctx, opt, i, x.clone()).await?;
}
out.set(stk, ctx, opt, txn, a, x).await?;
out.set(stk, ctx, opt, a, x).await?;
}
// This is the end of the expression
None => {
out.set(stk, ctx, opt, txn, alias.as_ref().unwrap_or(v), x)
out.set(stk, ctx, opt, alias.as_ref().unwrap_or(v), x)
.await?
}
}
@ -175,14 +173,14 @@ impl Fields {
// This expression is a variable fields expression
Value::Function(f) if f.name() == Some("type::fields") => {
// Process the function using variable field projections
let expr = expr.compute(stk, ctx, opt, txn, Some(doc)).await?;
let expr = expr.compute(stk, ctx, opt, Some(doc)).await?;
// Check if this is a single VALUE field expression
match self.single().is_some() {
false => {
// Get the first argument which is guaranteed to exist
let args = match f.args().first().unwrap() {
Value::Param(v) => {
v.compute(stk, ctx, opt, txn, Some(doc)).await?
v.compute(stk, ctx, opt, Some(doc)).await?
}
v => v.to_owned(),
};
@ -195,7 +193,7 @@ impl Fields {
// This value is always a string, so we can convert it
let name = syn::idiom(&name.to_raw_string())?;
// Check if this is a single VALUE field expression
out.set(stk, ctx, opt, txn, name.as_ref(), expr).await?
out.set(stk, ctx, opt, name.as_ref(), expr).await?
}
}
true => out = expr,
@ -204,14 +202,14 @@ impl Fields {
// This expression is a variable field expression
Value::Function(f) if f.name() == Some("type::field") => {
// Process the function using variable field projections
let expr = expr.compute(stk, ctx, opt, txn, Some(doc)).await?;
let expr = expr.compute(stk, ctx, opt, Some(doc)).await?;
// Check if this is a single VALUE field expression
match self.single().is_some() {
false => {
// Get the first argument which is guaranteed to exist
let name = match f.args().first().unwrap() {
Value::Param(v) => {
v.compute(stk, ctx, opt, txn, Some(doc)).await?
v.compute(stk, ctx, opt, Some(doc)).await?
}
v => v.to_owned(),
};
@ -223,17 +221,17 @@ impl Fields {
Cow::Owned(syn::idiom(&name.to_raw_string())?)
};
// Add the projected field to the output document
out.set(stk, ctx, opt, txn, name.as_ref(), expr).await?
out.set(stk, ctx, opt, name.as_ref(), expr).await?
}
true => out = expr,
}
}
// This expression is a normal field expression
_ => {
let expr = expr.compute(stk, ctx, opt, txn, Some(doc)).await?;
let expr = expr.compute(stk, ctx, opt, Some(doc)).await?;
// Check if this is a single VALUE field expression
match self.single().is_some() {
false => out.set(stk, ctx, opt, txn, name.as_ref(), expr).await?,
false => out.set(stk, ctx, opt, name.as_ref(), expr).await?,
true => out = expr,
}
}

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::fnc;
@ -184,7 +184,6 @@ impl Function {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Ensure futures are run
@ -198,12 +197,12 @@ impl Function {
let a = stk
.scope(|scope| {
try_join_all(
x.iter().map(|v| scope.run(|stk| v.compute(stk, ctx, opt, txn, doc))),
x.iter().map(|v| scope.run(|stk| v.compute(stk, ctx, opt, doc))),
)
})
.await?;
// Run the normal function
fnc::run(stk, ctx, opt, txn, doc, s, a).await
fnc::run(stk, ctx, opt, doc, s, a).await
}
Self::Custom(s, x) => {
// Check that a database is set to prevent a panic
@ -215,9 +214,11 @@ impl Function {
// Get the function definition
let val = {
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Get the function definition
run.get_and_cache_db_function(opt.ns(), opt.db(), s).await?
let val = run.get_and_cache_db_function(opt.ns(), opt.db(), s).await?;
drop(run);
val
};
// Check permissions
if opt.check_perms(Action::View) {
@ -232,8 +233,7 @@ impl Function {
// Disable permissions
let opt = &opt.new_with_perms(false);
// Process the PERMISSION clause
if !stk.run(|stk| e.compute(stk, ctx, opt, txn, doc)).await?.is_truthy()
{
if !stk.run(|stk| e.compute(stk, ctx, opt, doc)).await?.is_truthy() {
return Err(Error::FunctionPermissions {
name: s.to_owned(),
});
@ -265,7 +265,7 @@ impl Function {
let a = stk
.scope(|scope| {
try_join_all(
x.iter().map(|v| scope.run(|stk| v.compute(stk, ctx, opt, txn, doc))),
x.iter().map(|v| scope.run(|stk| v.compute(stk, ctx, opt, doc))),
)
})
.await?;
@ -276,7 +276,7 @@ impl Function {
ctx.add_value(name.to_raw(), val.coerce_to(kind)?);
}
// Run the custom function
stk.run(|stk| val.block.compute(stk, &ctx, opt, txn, doc)).await
stk.run(|stk| val.block.compute(stk, &ctx, opt, doc)).await
}
#[allow(unused_variables)]
Self::Script(s, x) => {
@ -288,13 +288,12 @@ impl Function {
let a = stk
.scope(|scope| {
try_join_all(
x.iter()
.map(|v| scope.run(|stk| v.compute(stk, ctx, opt, txn, doc))),
x.iter().map(|v| scope.run(|stk| v.compute(stk, ctx, opt, doc))),
)
})
.await?;
// Run the script function
fnc::script::run(ctx, opt, txn, doc, s, a).await
fnc::script::run(ctx, opt, doc, s, a).await
}
#[cfg(not(feature = "scripting"))]
{

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::block::Block;
@ -31,12 +31,11 @@ impl Future {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Process the future if enabled
match opt.futures {
true => stk.run(|stk| self.0.compute(stk, ctx, opt, txn, doc)).await?.ok(),
true => stk.run(|stk| self.0.compute(stk, ctx, opt, doc)).await?.ok(),
false => Ok(self.clone().into()),
}
}

View file

@ -1,6 +1,6 @@
use crate::cnf::ID_CHARS;
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::{escape::escape_rid, Array, Number, Object, Strand, Thing, Uuid, Value};
@ -186,17 +186,16 @@ impl Id {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Id, Error> {
match self {
Id::Number(v) => Ok(Id::Number(*v)),
Id::String(v) => Ok(Id::String(v.clone())),
Id::Array(v) => match v.compute(stk, ctx, opt, txn, doc).await? {
Id::Array(v) => match v.compute(stk, ctx, opt, doc).await? {
Value::Array(v) => Ok(Id::Array(v)),
_ => unreachable!(),
},
Id::Object(v) => match v.compute(stk, ctx, opt, txn, doc).await? {
Id::Object(v) => match v.compute(stk, ctx, opt, doc).await? {
Value::Object(v) => Ok(Id::Object(v)),
_ => unreachable!(),
},

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::statements::info::InfoStructure;
@ -160,28 +160,23 @@ impl Idiom {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
match self.first() {
// The starting part is a value
Some(Part::Start(v)) => {
v.compute(stk, ctx, opt, txn, doc)
v.compute(stk, ctx, opt, doc)
.await?
.get(stk, ctx, opt, txn, doc, self.as_ref().next())
.get(stk, ctx, opt, doc, self.as_ref().next())
.await?
.compute(stk, ctx, opt, txn, doc)
.compute(stk, ctx, opt, doc)
.await
}
// Otherwise use the current document
_ => match doc {
// There is a current document
Some(v) => {
v.doc
.get(stk, ctx, opt, txn, doc, self)
.await?
.compute(stk, ctx, opt, txn, doc)
.await
v.doc.get(stk, ctx, opt, doc, self).await?.compute(stk, ctx, opt, doc).await
}
// There isn't any document
None => Ok(Value::None),

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::number::Number;
@ -21,10 +21,9 @@ impl Limit {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<usize, Error> {
match self.0.compute(stk, ctx, opt, txn, doc).await {
match self.0.compute(stk, ctx, opt, doc).await {
// This is a valid limiting number
Ok(Value::Number(Number::Int(v))) if v >= 0 => Ok(v as usize),
// An invalid value was specified

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::value::Value;
@ -57,7 +57,6 @@ impl Model {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Ensure futures are run
@ -69,9 +68,12 @@ impl Model {
// Get the model definition
let val = {
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Get the function definition
run.get_and_cache_db_model(opt.ns(), opt.db(), &self.name, &self.version).await?
let val =
run.get_and_cache_db_model(opt.ns(), opt.db(), &self.name, &self.version).await?;
drop(run);
val
};
// Calculate the model path
let path = format!(
@ -95,7 +97,7 @@ impl Model {
// Disable permissions
let opt = &opt.new_with_perms(false);
// Process the PERMISSION clause
if !stk.run(|stk| e.compute(stk, ctx, opt, txn, doc)).await?.is_truthy() {
if !stk.run(|stk| e.compute(stk, ctx, opt, doc)).await?.is_truthy() {
return Err(Error::FunctionPermissions {
name: self.name.to_owned(),
});
@ -106,9 +108,7 @@ impl Model {
// Compute the function arguments
let mut args = stk
.scope(|stk| {
try_join_all(
self.args.iter().map(|v| stk.run(|stk| v.compute(stk, ctx, opt, txn, doc))),
)
try_join_all(self.args.iter().map(|v| stk.run(|stk| v.compute(stk, ctx, opt, doc))))
})
.await?;
// Check the minimum argument length
@ -224,7 +224,6 @@ impl Model {
_stk: &mut Stk,
_ctx: &Context<'_>,
_opt: &Options,
_txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
Err(Error::InvalidModel {

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::{
@ -220,12 +220,11 @@ impl Object {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
let mut x = BTreeMap::new();
for (k, v) in self.iter() {
match v.compute(stk, ctx, opt, txn, doc).await {
match v.compute(stk, ctx, opt, doc).await {
Ok(v) => x.insert(k.clone(), v),
Err(e) => return Err(e),
};

View file

@ -1,6 +1,6 @@
use crate::{
ctx::Context,
dbs::{Options, Transaction},
dbs::Options,
doc::CursorDoc,
err::Error,
iam::Action,
@ -52,7 +52,6 @@ impl Param {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Find the variable by name
@ -60,21 +59,21 @@ impl Param {
// This is a special param
"this" | "self" => match doc {
// The base document exists
Some(v) => v.doc.compute(stk, ctx, opt, txn, doc).await,
Some(v) => v.doc.compute(stk, ctx, opt, doc).await,
// The base document does not exist
None => Ok(Value::None),
},
// This is a normal param
v => match ctx.value(v) {
// The param has been set locally
Some(v) => v.compute(stk, ctx, opt, txn, doc).await,
Some(v) => v.compute(stk, ctx, opt, doc).await,
// The param has not been set locally
None => {
// Check that a database is set to prevent a panic
opt.valid_for_db()?;
let val = {
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Get the param definition
run.get_and_cache_db_param(opt.ns(), opt.db(), v).await
};
@ -95,7 +94,7 @@ impl Param {
// Disable permissions
let opt = &opt.new_with_perms(false);
// Process the PERMISSION clause
if !e.compute(stk, ctx, opt, txn, doc).await?.is_truthy() {
if !e.compute(stk, ctx, opt, doc).await?.is_truthy() {
return Err(Error::ParamPermissions {
name: v.to_owned(),
});
@ -104,7 +103,7 @@ impl Param {
}
}
// Return the computed value
val.value.compute(stk, ctx, opt, txn, doc).await
val.value.compute(stk, ctx, opt, doc).await
}
// The param has not been set globally
Err(_) => Ok(Value::None),

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::Cond;
@ -162,19 +162,18 @@ impl Range {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
Ok(Value::Range(Box::new(Range {
tb: self.tb.clone(),
beg: match &self.beg {
Bound::Included(id) => Bound::Included(id.compute(stk, ctx, opt, txn, doc).await?),
Bound::Excluded(id) => Bound::Excluded(id.compute(stk, ctx, opt, txn, doc).await?),
Bound::Included(id) => Bound::Included(id.compute(stk, ctx, opt, doc).await?),
Bound::Excluded(id) => Bound::Excluded(id.compute(stk, ctx, opt, doc).await?),
Bound::Unbounded => Bound::Unbounded,
},
end: match &self.end {
Bound::Included(id) => Bound::Included(id.compute(stk, ctx, opt, txn, doc).await?),
Bound::Excluded(id) => Bound::Excluded(id.compute(stk, ctx, opt, txn, doc).await?),
Bound::Included(id) => Bound::Included(id.compute(stk, ctx, opt, doc).await?),
Bound::Excluded(id) => Bound::Excluded(id.compute(stk, ctx, opt, doc).await?),
Bound::Unbounded => Bound::Unbounded,
},
})))

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::number::Number;
@ -21,10 +21,9 @@ impl Start {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<usize, Error> {
match self.0.compute(stk, ctx, opt, txn, doc).await {
match self.0.compute(stk, ctx, opt, doc).await {
// This is a valid starting number
Ok(Value::Number(Number::Int(v))) if v >= 0 => Ok(v as usize),
// An invalid value was specified

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::statements::rebuild::RebuildStatement;
@ -140,37 +140,36 @@ impl Statement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
match self {
Self::Analyze(v) => v.compute(ctx, opt, txn, doc).await,
Self::Break(v) => v.compute(ctx, opt, txn, doc).await,
Self::Continue(v) => v.compute(ctx, opt, txn, doc).await,
Self::Create(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Delete(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Define(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Foreach(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Ifelse(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Info(v) => v.compute(ctx, opt, txn, doc).await,
Self::Insert(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Kill(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Live(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Output(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Relate(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Rebuild(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Remove(v) => v.compute(ctx, opt, txn, doc).await,
Self::Select(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Set(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Show(v) => v.compute(ctx, opt, txn, doc).await,
Self::Sleep(v) => v.compute(ctx, opt, txn, doc).await,
Self::Throw(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Update(v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Analyze(v) => v.compute(ctx, opt, doc).await,
Self::Break(v) => v.compute(ctx, opt, doc).await,
Self::Continue(v) => v.compute(ctx, opt, doc).await,
Self::Create(v) => v.compute(stk, ctx, opt, doc).await,
Self::Delete(v) => v.compute(stk, ctx, opt, doc).await,
Self::Define(v) => v.compute(stk, ctx, opt, doc).await,
Self::Foreach(v) => v.compute(stk, ctx, opt, doc).await,
Self::Ifelse(v) => v.compute(stk, ctx, opt, doc).await,
Self::Info(v) => v.compute(ctx, opt, doc).await,
Self::Insert(v) => v.compute(stk, ctx, opt, doc).await,
Self::Kill(v) => v.compute(stk, ctx, opt, doc).await,
Self::Live(v) => v.compute(stk, ctx, opt, doc).await,
Self::Output(v) => v.compute(stk, ctx, opt, doc).await,
Self::Relate(v) => v.compute(stk, ctx, opt, doc).await,
Self::Rebuild(v) => v.compute(stk, ctx, opt, doc).await,
Self::Remove(v) => v.compute(ctx, opt, doc).await,
Self::Select(v) => v.compute(stk, ctx, opt, doc).await,
Self::Set(v) => v.compute(stk, ctx, opt, doc).await,
Self::Show(v) => v.compute(ctx, opt, doc).await,
Self::Sleep(v) => v.compute(ctx, opt, doc).await,
Self::Throw(v) => v.compute(stk, ctx, opt, doc).await,
Self::Update(v) => v.compute(stk, ctx, opt, doc).await,
Self::Value(v) => {
// Ensure futures are processed
let opt = &opt.new_with_futures(true);
// Process the output value
v.compute(stk, ctx, opt, txn, doc).await
v.compute(stk, ctx, opt, doc).await
}
_ => unreachable!(),
}

View file

@ -1,6 +1,5 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Transaction;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -32,7 +31,6 @@ impl AnalyzeStatement {
&self,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
match self {
@ -40,8 +38,8 @@ impl AnalyzeStatement {
// Allowed to run?
opt.is_allowed(Action::View, ResourceKind::Index, &Base::Db)?;
// Read the index
let ix = txn
.lock()
let ix = ctx
.tx_lock()
.await
.get_and_cache_tb_index(opt.ns(), opt.db(), tb.as_str(), idx.as_str())
.await?;
@ -50,20 +48,13 @@ impl AnalyzeStatement {
// Index operation dispatching
let value: Value = match &ix.index {
Index::Search(p) => {
let ft = FtIndex::new(
ctx.get_index_stores(),
opt,
txn,
p.az.as_str(),
ikb,
p,
TransactionType::Read,
)
.await?;
ft.statistics(txn).await?.into()
let ft =
FtIndex::new(ctx, opt, p.az.as_str(), ikb, p, TransactionType::Read)
.await?;
ft.statistics(ctx).await?.into()
}
Index::MTree(p) => {
let mut tx = txn.lock().await;
let mut tx = ctx.tx_lock().await;
let mt = MTreeIndex::new(
ctx.get_index_stores(),
&mut tx,

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::value::Value;
@ -24,7 +24,6 @@ impl BreakStatement {
&self,
_ctx: &Context<'_>,
_opt: &Options,
_txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
Err(Error::Break)

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::Value;
@ -24,7 +24,6 @@ impl ContinueStatement {
&self,
_ctx: &Context<'_>,
_opt: &Options,
_txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
Err(Error::Continue)

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Iterator, Options, Statement, Transaction};
use crate::dbs::{Iterator, Options, Statement};
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::{Data, Output, Timeout, Value, Values};
@ -40,7 +40,6 @@ impl CreateStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Valid options?
@ -53,8 +52,8 @@ impl CreateStatement {
let opt = &opt.new_with_futures(false);
// Loop over the create targets
for w in self.what.0.iter() {
let v = w.compute(stk, ctx, opt, txn, doc).await?;
i.prepare(stk, ctx, opt, txn, &stm, v).await.map_err(|e| match e {
let v = w.compute(stk, ctx, opt, doc).await?;
i.prepare(stk, ctx, opt, &stm, v).await.map_err(|e| match e {
Error::InvalidStatementTarget {
value: v,
} => Error::CreateStatement {
@ -64,7 +63,7 @@ impl CreateStatement {
})?;
}
// Output the results
match i.output(stk, ctx, opt, txn, &stm).await? {
match i.output(stk, ctx, opt, &stm).await? {
// This is a single record result
Value::Array(mut a) if self.only => match a.len() {
// There was exactly one result

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -38,9 +38,8 @@ impl DefineAccessStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
opt.is_allowed(Action::Edit, ResourceKind::Actor, &self.base)?;
@ -48,7 +47,7 @@ impl DefineAccessStatement {
match &self.base {
Base::Ns => {
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if access method already exists
@ -73,7 +72,7 @@ impl DefineAccessStatement {
}
Base::Db => {
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if access method already exists

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -28,15 +28,14 @@ pub struct DefineAnalyzerStatement {
impl DefineAnalyzerStatement {
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Analyzer, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if analyzer already exists

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -27,15 +27,14 @@ impl DefineDatabaseStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Database, &Base::Ns)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if database already exists

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -28,15 +28,14 @@ impl DefineEventStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Event, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if event already exists

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -39,15 +39,14 @@ impl DefineFieldStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Field, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if field already exists

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -31,15 +31,14 @@ impl DefineFunctionStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Function, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if function already exists

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Force, Options, Transaction};
use crate::dbs::{Force, Options};
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -35,13 +35,12 @@ impl DefineIndexStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Index, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if index already exists
@ -104,7 +103,7 @@ impl DefineIndexStatement {
what: Values(vec![Value::Table(self.what.clone().into())]),
..UpdateStatement::default()
};
stm.compute(stk, ctx, opt, txn, doc).await?;
stm.compute(stk, ctx, opt, doc).await?;
// Ok all good
Ok(Value::None)
}

View file

@ -26,7 +26,6 @@ pub use user::DefineUserStatement;
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Transaction;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::value::Value;
@ -66,22 +65,21 @@ impl DefineStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
match self {
Self::Namespace(ref v) => v.compute(ctx, opt, txn, doc).await,
Self::Database(ref v) => v.compute(ctx, opt, txn, doc).await,
Self::Function(ref v) => v.compute(ctx, opt, txn, doc).await,
Self::Param(ref v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Table(ref v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Event(ref v) => v.compute(ctx, opt, txn, doc).await,
Self::Field(ref v) => v.compute(ctx, opt, txn, doc).await,
Self::Index(ref v) => v.compute(stk, ctx, opt, txn, doc).await,
Self::Analyzer(ref v) => v.compute(ctx, opt, txn, doc).await,
Self::User(ref v) => v.compute(ctx, opt, txn, doc).await,
Self::Model(ref v) => v.compute(ctx, opt, txn, doc).await,
Self::Access(ref v) => v.compute(ctx, opt, txn, doc).await,
Self::Namespace(ref v) => v.compute(ctx, opt, doc).await,
Self::Database(ref v) => v.compute(ctx, opt, doc).await,
Self::Function(ref v) => v.compute(ctx, opt, doc).await,
Self::Param(ref v) => v.compute(stk, ctx, opt, doc).await,
Self::Table(ref v) => v.compute(stk, ctx, opt, doc).await,
Self::Event(ref v) => v.compute(ctx, opt, doc).await,
Self::Field(ref v) => v.compute(ctx, opt, doc).await,
Self::Index(ref v) => v.compute(stk, ctx, opt, doc).await,
Self::Analyzer(ref v) => v.compute(ctx, opt, doc).await,
Self::User(ref v) => v.compute(ctx, opt, doc).await,
Self::Model(ref v) => v.compute(ctx, opt, doc).await,
Self::Access(ref v) => v.compute(ctx, opt, doc).await,
}
}
}

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -52,15 +52,14 @@ impl DefineModelStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Model, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if model already exists

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -26,9 +26,8 @@ impl DefineNamespaceStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
@ -36,7 +35,7 @@ impl DefineNamespaceStatement {
// Process the statement
let key = crate::key::root::ns::new(&self.name);
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if namespace already exists

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -32,13 +32,12 @@ impl DefineParamStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Parameter, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if param already exists
@ -55,7 +54,7 @@ impl DefineParamStatement {
key,
DefineParamStatement {
// Compute the param
value: self.value.compute(stk, ctx, opt, txn, doc).await?,
value: self.value.compute(stk, ctx, opt, doc).await?,
// Don't persist the "IF NOT EXISTS" clause to schema
if_not_exists: false,
..self.clone()

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Force, Options, Transaction};
use crate::dbs::{Force, Options};
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -46,13 +46,12 @@ impl DefineTableStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Table, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if table already exists
@ -133,7 +132,7 @@ impl DefineTableStatement {
what: Values(vec![Value::Table(v.clone())]),
..UpdateStatement::default()
};
stm.compute(stk, ctx, opt, txn, doc).await?;
stm.compute(stk, ctx, opt, doc).await?;
}
} else if dt.changefeed.is_some() {
run.record_table_change(opt.ns(), opt.db(), self.name.0.as_str(), &dt);

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
@ -80,9 +80,8 @@ impl DefineUserStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
@ -91,7 +90,7 @@ impl DefineUserStatement {
match self.base {
Base::Root => {
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if user already exists
@ -116,7 +115,7 @@ impl DefineUserStatement {
}
Base::Ns => {
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if user already exists
@ -143,7 +142,7 @@ impl DefineUserStatement {
}
Base::Db => {
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Clear the cache
run.clear_cache();
// Check if user already exists

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Iterator, Options, Statement, Transaction};
use crate::dbs::{Iterator, Options, Statement};
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::{Cond, Output, Timeout, Value, Values};
@ -34,7 +34,6 @@ impl DeleteStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Valid options?
@ -47,8 +46,8 @@ impl DeleteStatement {
let opt = &opt.new_with_futures(false).with_projections(false);
// Loop over the delete targets
for w in self.what.0.iter() {
let v = w.compute(stk, ctx, opt, txn, doc).await?;
i.prepare(stk, ctx, opt, txn, &stm, v).await.map_err(|e| match e {
let v = w.compute(stk, ctx, opt, doc).await?;
i.prepare(stk, ctx, opt, &stm, v).await.map_err(|e| match e {
Error::InvalidStatementTarget {
value: v,
} => Error::DeleteStatement {
@ -58,7 +57,7 @@ impl DeleteStatement {
})?;
}
// Output the results
match i.output(stk, ctx, opt, txn, &stm).await? {
match i.output(stk, ctx, opt, &stm).await? {
// This is a single record result
Value::Array(mut a) if self.only => match a.len() {
// There was exactly one result

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::{block::Entry, Block, Param, Value};
@ -32,11 +32,10 @@ impl ForeachStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Check the loop data
match &self.range.compute(stk, ctx, opt, txn, doc).await? {
match &self.range.compute(stk, ctx, opt, doc).await? {
Value::Array(arr) => {
// Loop over the values
'foreach: for v in arr.iter() {
@ -44,55 +43,38 @@ impl ForeachStatement {
let mut ctx = Context::new(ctx);
// Set the current parameter
let key = self.param.0.to_raw();
let val = stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await?;
let val = stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await?;
ctx.add_value(key, val);
// Loop over the code block statements
for v in self.block.iter() {
// Compute each block entry
let res = match v {
Entry::Set(v) => {
let val =
stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await?;
let val = stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await?;
ctx.add_value(v.name.to_owned(), val);
Ok(Value::None)
}
Entry::Value(v) => {
stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await
}
Entry::Break(v) => v.compute(&ctx, opt, txn, doc).await,
Entry::Continue(v) => v.compute(&ctx, opt, txn, doc).await,
Entry::Value(v) => stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await,
Entry::Break(v) => v.compute(&ctx, opt, doc).await,
Entry::Continue(v) => v.compute(&ctx, opt, doc).await,
Entry::Foreach(v) => {
stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await
stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await
}
Entry::Ifelse(v) => {
stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await
}
Entry::Select(v) => {
stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await
}
Entry::Create(v) => {
stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await
}
Entry::Update(v) => {
stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await
}
Entry::Delete(v) => {
stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await
}
Entry::Relate(v) => {
stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await
}
Entry::Insert(v) => {
stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await
}
Entry::Define(v) => v.compute(stk, &ctx, opt, txn, doc).await,
Entry::Rebuild(v) => v.compute(stk, &ctx, opt, txn, doc).await,
Entry::Remove(v) => v.compute(&ctx, opt, txn, doc).await,
Entry::Ifelse(v) => stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await,
Entry::Select(v) => stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await,
Entry::Create(v) => stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await,
Entry::Update(v) => stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await,
Entry::Delete(v) => stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await,
Entry::Relate(v) => stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await,
Entry::Insert(v) => stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await,
Entry::Define(v) => v.compute(stk, &ctx, opt, doc).await,
Entry::Rebuild(v) => v.compute(stk, &ctx, opt, doc).await,
Entry::Remove(v) => v.compute(&ctx, opt, doc).await,
Entry::Output(v) => {
return stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await;
return stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await;
}
Entry::Throw(v) => {
return stk.run(|stk| v.compute(stk, &ctx, opt, txn, doc)).await;
return stk.run(|stk| v.compute(stk, &ctx, opt, doc)).await;
}
};
// Catch any special errors

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::fmt::{fmt_separated_by, is_pretty, pretty_indent, Fmt, Pretty};
@ -43,17 +43,16 @@ impl IfelseStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
for (ref cond, ref then) in &self.exprs {
let v = cond.compute(stk, ctx, opt, txn, doc).await?;
let v = cond.compute(stk, ctx, opt, doc).await?;
if v.is_truthy() {
return then.compute(stk, ctx, opt, txn, doc).await;
return then.compute(stk, ctx, opt, doc).await;
}
}
match self.close {
Some(ref v) => v.compute(stk, ctx, opt, txn, doc).await,
Some(ref v) => v.compute(stk, ctx, opt, doc).await,
None => Ok(Value::None),
}
}

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::Action;
@ -66,9 +66,8 @@ impl InfoStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Allowed to run?
@ -77,7 +76,7 @@ impl InfoStatement {
// Allowed to run?
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Root)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Create the result set
let mut res = Object::default();
// Process the namespaces
@ -99,7 +98,7 @@ impl InfoStatement {
// Allowed to run?
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Ns)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Create the result set
let mut res = Object::default();
// Process the databases
@ -127,7 +126,7 @@ impl InfoStatement {
// Allowed to run?
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Create the result set
let mut res = Object::default();
// Process the users
@ -179,7 +178,7 @@ impl InfoStatement {
// Allowed to run?
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Create the result set
let mut res = Object::default();
// Process the events
@ -221,7 +220,7 @@ impl InfoStatement {
opt.is_allowed(Action::View, ResourceKind::Actor, &base)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Process the user
let res = match base {
Base::Root => run.get_root_user(user).await?,
@ -236,7 +235,7 @@ impl InfoStatement {
// Allowed to run?
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Root)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Create the result set
let mut res = Object::default();
// Process the namespaces
@ -250,7 +249,7 @@ impl InfoStatement {
// Allowed to run?
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Ns)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Create the result set
let mut res = Object::default();
// Process the databases
@ -269,7 +268,7 @@ impl InfoStatement {
// Allowed to run?
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Create the result set
let mut res = Object::default();
// Process the users
@ -316,7 +315,7 @@ impl InfoStatement {
// Allowed to run?
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Db)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Create the result set
let mut res = Object::default();
// Process the events
@ -353,7 +352,7 @@ impl InfoStatement {
opt.is_allowed(Action::View, ResourceKind::Actor, &base)?;
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Process the user
let res = match base {
Base::Root => run.get_root_user(user).await?,

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Iterable, Iterator, Options, Statement, Transaction};
use crate::dbs::{Iterable, Iterator, Options, Statement};
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::sql::{Data, Output, Timeout, Value};
@ -34,7 +34,6 @@ impl InsertStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Valid options?
@ -44,7 +43,7 @@ impl InsertStatement {
// Ensure futures are stored
let opt = &opt.new_with_futures(false).with_projections(false);
// Parse the expression
match self.into.compute(stk, ctx, opt, txn, doc).await? {
match self.into.compute(stk, ctx, opt, doc).await? {
Value::Table(into) => match &self.data {
// Check if this is a traditional statement
Data::ValuesExpression(v) => {
@ -53,8 +52,8 @@ impl InsertStatement {
let mut o = Value::base();
// Set each field from the expression
for (k, v) in v.iter() {
let v = v.compute(stk, ctx, opt, txn, None).await?;
o.set(stk, ctx, opt, txn, k, v).await?;
let v = v.compute(stk, ctx, opt, None).await?;
o.set(stk, ctx, opt, k, v).await?;
}
// Specify the new table record id
let id = o.rid().generate(&into, true)?;
@ -64,7 +63,7 @@ impl InsertStatement {
}
// Check if this is a modern statement
Data::SingleExpression(v) => {
let v = v.compute(stk, ctx, opt, txn, doc).await?;
let v = v.compute(stk, ctx, opt, doc).await?;
match v {
Value::Array(v) => {
for v in v {
@ -98,7 +97,7 @@ impl InsertStatement {
// Assign the statement
let stm = Statement::from(self);
// Output the results
i.output(stk, ctx, opt, txn, &stm).await
i.output(stk, ctx, opt, &stm).await
}
}

View file

@ -6,7 +6,7 @@ use revision::revisioned;
use serde::{Deserialize, Serialize};
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::fflags::FFLAGS;
@ -31,7 +31,6 @@ impl KillStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Is realtime enabled?
@ -41,7 +40,7 @@ impl KillStatement {
// Resolve live query id
let live_query_id = match &self.id {
Value::Uuid(id) => *id,
Value::Param(param) => match param.compute(stk, ctx, opt, txn, None).await? {
Value::Param(param) => match param.compute(stk, ctx, opt, None).await? {
Value::Uuid(id) => id,
Value::Strand(id) => match uuid::Uuid::try_parse(&id) {
Ok(id) => Uuid(id),
@ -75,7 +74,7 @@ impl KillStatement {
}
};
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
if FFLAGS.change_feed_live_queries.enabled() {
run.pre_commit_register_async_event(TrackedResult::KillQuery(KillEntry {
live_id: live_query_id,
@ -155,10 +154,11 @@ mod test {
let ds = Datastore::new("memory").await.unwrap();
let tx =
ds.transaction(TransactionType::Write, LockType::Optimistic).await.unwrap().enclose();
let ctx = ctx.set_transaction(tx.clone());
let mut stack = reblessive::tree::TreeStack::new();
stack.enter(|stk| res.compute(stk, &ctx, &opt, &tx, None)).finish().await.unwrap();
stack.enter(|stk| res.compute(stk, &ctx, &opt, None)).finish().await.unwrap();
let mut tx = tx.lock().await;
tx.commit().await.unwrap();

View file

@ -1,5 +1,5 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::{Error, LiveQueryCause};
use crate::fflags::FFLAGS;
@ -82,7 +82,6 @@ impl LiveStatement {
stk: &mut Stk,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
// Is realtime enabled?
@ -106,8 +105,8 @@ impl LiveStatement {
let id = stm.id.0;
match FFLAGS.change_feed_live_queries.enabled() {
true => {
let mut run = txn.lock().await;
match stm.what.compute(stk, ctx, opt, txn, doc).await? {
let mut run = ctx.tx_lock().await;
match stm.what.compute(stk, ctx, opt, doc).await? {
Value::Table(tb) => {
// We modify the table as it can be a $PARAM and the compute evaluates that
let mut stm = stm;
@ -134,9 +133,9 @@ impl LiveStatement {
}
false => {
// Claim transaction
let mut run = txn.lock().await;
let mut run = ctx.tx_lock().await;
// Process the live query table
match stm.what.compute(stk, ctx, opt, txn, doc).await? {
match stm.what.compute(stk, ctx, opt, doc).await? {
Value::Table(tb) => {
// Store the current Node ID
stm.node = nid.into();

Some files were not shown because too many files have changed in this diff Show more