Remove Context lifetimes ()

This commit is contained in:
Emmanuel Keller 2024-08-15 17:01:02 +01:00 committed by GitHub
parent d7b392cf8b
commit 6e9d04d4d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
149 changed files with 971 additions and 801 deletions

View file

@ -1,11 +1,10 @@
use std::borrow::Cow;
use std::collections::HashMap;
use crate::cf::{TableMutation, TableMutations};
use crate::doc::CursorValue;
use crate::kvs::Key;
use crate::sql::statements::DefineTableStatement;
use crate::sql::thing::Thing;
use crate::sql::value::Value;
use crate::sql::Idiom;
// PreparedWrite is a tuple of (versionstamp key, key prefix, key suffix, serialized table mutations).
@ -71,18 +70,18 @@ impl Writer {
db: &str,
tb: &str,
id: Thing,
previous: Cow<'_, Value>,
current: Cow<'_, Value>,
previous: CursorValue,
current: CursorValue,
store_difference: bool,
) {
if current.is_some() {
if current.as_ref().is_some() {
self.buf.push(
ns.to_string(),
db.to_string(),
tb.to_string(),
match store_difference {
true => {
if previous.is_none() {
if previous.as_ref().is_none() {
TableMutation::Set(id, current.into_owned())
} else {
// We intentionally record the patches in reverse (current -> previous)
@ -147,7 +146,6 @@ impl Writer {
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use std::time::Duration;
use crate::cf::{ChangeSet, DatabaseMutation, TableMutation, TableMutations};
@ -190,15 +188,15 @@ mod tests {
tb: TB.to_owned(),
id: Id::String("A".to_string()),
};
let value_a: super::Value = "a".into();
let previous = Cow::from(Value::None);
let value_a: Value = "a".into();
let previous = Value::None;
tx1.record_change(
NS,
DB,
TB,
&thing_a,
previous.clone(),
Cow::Borrowed(&value_a),
previous.clone().into(),
value_a.into(),
DONT_STORE_PREVIOUS,
);
tx1.complete_changes(true).await.unwrap();
@ -215,8 +213,8 @@ mod tests {
DB,
TB,
&thing_c,
previous.clone(),
Cow::Borrowed(&value_c),
previous.clone().into(),
value_c.into(),
DONT_STORE_PREVIOUS,
);
tx2.complete_changes(true).await.unwrap();
@ -233,8 +231,8 @@ mod tests {
DB,
TB,
&thing_b,
previous.clone(),
Cow::Borrowed(&value_b),
previous.clone().into(),
value_b.into(),
DONT_STORE_PREVIOUS,
);
let thing_c2 = Thing {
@ -247,8 +245,8 @@ mod tests {
DB,
TB,
&thing_c2,
previous.clone(),
Cow::Borrowed(&value_c2),
previous.clone().into(),
value_c2.into(),
DONT_STORE_PREVIOUS,
);
tx3.complete_changes(true).await.unwrap();
@ -536,14 +534,14 @@ mod tests {
id: Id::String(id),
};
let value_a: Value = "a".into();
let previous = Cow::from(Value::None);
let previous = Value::None.into();
tx.lock().await.record_change(
NS,
DB,
TB,
&thing,
previous.clone(),
Cow::Borrowed(&value_a),
previous,
value_a.into(),
DONT_STORE_PREVIOUS,
);
tx.lock().await.complete_changes(true).await.unwrap();

View file

@ -39,20 +39,23 @@ impl<'a> From<&'a Value> for Cow<'a, Value> {
Cow::Borrowed(v)
}
}
pub type Context = Arc<MutableContext>;
#[non_exhaustive]
pub struct Context<'a> {
pub struct MutableContext {
// An optional parent context.
parent: Option<&'a Context<'a>>,
parent: Option<Context>,
// An optional deadline.
deadline: Option<Instant>,
// Whether or not this context is cancelled.
cancelled: Arc<AtomicBool>,
// A collection of read only values stored in this context.
values: HashMap<Cow<'static, str>, Cow<'a, Value>>,
values: HashMap<Cow<'static, str>, Arc<Value>>,
// Stores the notification channel if available
notifications: Option<Sender<Notification>>,
// An optional query planner
query_planner: Option<&'a QueryPlanner<'a>>,
query_planner: Option<Arc<QueryPlanner>>,
// An optional query executor
query_executor: Option<QueryExecutor>,
// An optional iteration stage
@ -76,19 +79,21 @@ pub struct Context<'a> {
isolated: bool,
}
impl<'a> Default for Context<'a> {
impl Default for MutableContext {
fn default() -> Self {
Context::background()
MutableContext::background()
}
}
impl<'a> From<Transaction> for Context<'a> {
impl From<Transaction> for MutableContext {
fn from(txn: Transaction) -> Self {
Context::background().with_transaction(Arc::new(txn))
let mut ctx = MutableContext::background();
ctx.set_transaction(Arc::new(txn));
ctx
}
}
impl<'a> Debug for Context<'a> {
impl Debug for MutableContext {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Context")
.field("parent", &self.parent)
@ -99,7 +104,7 @@ impl<'a> Debug for Context<'a> {
}
}
impl<'a> Context<'a> {
impl MutableContext {
pub(crate) fn from_ds(
time_out: Option<Duration>,
capabilities: Capabilities,
@ -112,7 +117,7 @@ impl<'a> Context<'a> {
feature = "kv-tikv",
))]
temporary_directory: Option<Arc<PathBuf>>,
) -> Result<Context<'a>, Error> {
) -> Result<MutableContext, Error> {
let mut ctx = Self {
values: HashMap::default(),
parent: None,
@ -167,14 +172,13 @@ impl<'a> Context<'a> {
}
/// Create a new child from a frozen context.
pub fn new(parent: &'a Context) -> Self {
Context {
pub fn new(parent: &Context) -> Self {
MutableContext {
values: HashMap::default(),
parent: Some(parent),
deadline: parent.deadline,
cancelled: Arc::new(AtomicBool::new(false)),
notifications: parent.notifications.clone(),
query_planner: parent.query_planner,
query_planner: parent.query_planner.clone(),
query_executor: parent.query_executor.clone(),
iteration_stage: parent.iteration_stage.clone(),
capabilities: parent.capabilities.clone(),
@ -189,18 +193,28 @@ impl<'a> Context<'a> {
temporary_directory: parent.temporary_directory.clone(),
transaction: parent.transaction.clone(),
isolated: false,
parent: Some(parent.clone()),
}
}
pub(crate) fn freeze(self) -> Context {
Arc::new(self)
}
pub(crate) fn unfreeze(ctx: Context) -> Result<MutableContext, Error> {
match Arc::try_unwrap(ctx) {
Ok(inner) => Ok(inner),
Err(_) => Err(Error::Unreachable("Context::unfreeze")),
}
}
/// Create a new child from a frozen context.
pub fn new_isolated(parent: &'a Context) -> Self {
Context {
pub fn new_isolated(parent: &Context) -> Self {
Self {
values: HashMap::default(),
parent: Some(parent),
deadline: parent.deadline,
cancelled: Arc::new(AtomicBool::new(false)),
notifications: parent.notifications.clone(),
query_planner: parent.query_planner,
query_planner: parent.query_planner.clone(),
query_executor: parent.query_executor.clone(),
iteration_stage: parent.iteration_stage.clone(),
capabilities: parent.capabilities.clone(),
@ -215,17 +229,17 @@ impl<'a> Context<'a> {
temporary_directory: parent.temporary_directory.clone(),
transaction: parent.transaction.clone(),
isolated: true,
parent: Some(parent.clone()),
}
}
/// Add a value to the context. It overwrites any previously set values
/// with the same key.
pub fn add_value<K, V>(&mut self, key: K, value: V)
pub fn add_value<K>(&mut self, key: K, value: Arc<Value>)
where
K: Into<Cow<'static, str>>,
V: Into<Cow<'a, Value>>,
{
self.values.insert(key.into(), value.into());
self.values.insert(key.into(), value);
}
/// Add cancellation to the context. The value that is returned will cancel
@ -263,8 +277,8 @@ impl<'a> Context<'a> {
self.notifications = chn.cloned()
}
pub(crate) fn set_query_planner(&mut self, qp: &'a QueryPlanner) {
self.query_planner = Some(qp);
pub(crate) fn set_query_planner(&mut self, qp: QueryPlanner) {
self.query_planner = Some(Arc::new(qp));
}
pub(crate) fn set_query_executor(&mut self, qe: QueryExecutor) {
@ -279,11 +293,6 @@ impl<'a> Context<'a> {
self.transaction = Some(txn);
}
pub(crate) fn with_transaction(mut self, txn: Arc<Transaction>) -> Self {
self.transaction = Some(txn);
self
}
pub(crate) fn tx(&self) -> Arc<Transaction> {
self.transaction
.clone()
@ -301,7 +310,7 @@ impl<'a> Context<'a> {
}
pub(crate) fn get_query_planner(&self) -> Option<&QueryPlanner> {
self.query_planner
self.query_planner.as_ref().map(|qp| qp.as_ref())
}
pub(crate) fn get_query_executor(&self) -> Option<&QueryExecutor> {
@ -323,7 +332,7 @@ impl<'a> Context<'a> {
match self.deadline {
Some(deadline) if deadline <= Instant::now() => Some(Reason::Timedout),
_ if self.cancelled.load(Ordering::Relaxed) => Some(Reason::Canceled),
_ => match self.parent {
_ => match &self.parent {
Some(ctx) => ctx.done(),
_ => None,
},
@ -361,11 +370,8 @@ impl<'a> Context<'a> {
/// provided key, then this will return None.
pub fn value(&self, key: &str) -> Option<&Value> {
match self.values.get(key) {
Some(v) => match v {
Cow::Borrowed(v) => Some(*v),
Cow::Owned(v) => Some(v),
},
None if !self.isolated => match self.parent {
Some(v) => Some(v.as_ref()),
None if !self.isolated => match &self.parent {
Some(p) => p.value(key),
_ => None,
},
@ -378,7 +384,7 @@ impl<'a> Context<'a> {
pub fn cancellation(&self) -> crate::ctx::cancellation::Cancellation {
crate::ctx::cancellation::Cancellation::new(
self.deadline,
std::iter::successors(Some(self), |ctx| ctx.parent)
std::iter::successors(Some(self), |ctx| ctx.parent.as_ref().map(|c| c.as_ref()))
.map(|ctx| ctx.cancelled.clone())
.collect(),
)

View file

@ -17,7 +17,7 @@ pub(crate) struct SyncDistinct {
}
impl SyncDistinct {
pub(super) fn new(ctx: &Context<'_>) -> Option<Self> {
pub(super) fn new(ctx: &Context) -> Option<Self> {
if let Some(pla) = ctx.get_query_planner() {
if pla.requires_distinct() {
return Some(Self::default());
@ -27,7 +27,7 @@ impl SyncDistinct {
}
pub(super) fn check_already_processed(&mut self, pro: &Processed) -> bool {
if let Some(key) = pro.rid.as_ref().map(std::convert::Into::<Vec<u8>>::into) {
if let Some(key) = pro.rid.as_ref().map(|r| r.as_ref().into()) {
if self.processed.get(&key).is_some() {
true
} else {
@ -48,7 +48,7 @@ pub(crate) struct AsyncDistinct {
#[cfg(not(target_arch = "wasm32"))]
impl AsyncDistinct {
pub(super) fn new(ctx: &Context<'_>) -> Option<Self> {
pub(super) fn new(ctx: &Context) -> Option<Self> {
if let Some(pla) = ctx.get_query_planner() {
if pla.requires_distinct() {
return Some(Self::default());

View file

@ -1,4 +1,4 @@
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
use crate::dbs::response::Response;
use crate::dbs::Force;
use crate::dbs::Notification;
@ -143,7 +143,7 @@ impl<'a> Executor<'a> {
}
/// Consume the live query notifications
async fn clear(&self, _: &Context<'_>, mut rcv: Receiver<Notification>) {
async fn clear(&self, _: &Context, mut rcv: Receiver<Notification>) {
spawn(async move {
while rcv.next().await.is_some() {
// Ignore notification
@ -153,7 +153,7 @@ impl<'a> Executor<'a> {
/// Flush notifications from a buffer channel (live queries) to the committed notification channel.
/// This is because we don't want to broadcast notifications to the user for failed transactions.
async fn flush(&self, ctx: &Context<'_>, mut rcv: Receiver<Notification>) {
async fn flush(&self, ctx: &Context, mut rcv: Receiver<Notification>) {
let sender = ctx.notifications();
spawn(async move {
while let Some(notification) = rcv.next().await {
@ -166,24 +166,28 @@ impl<'a> Executor<'a> {
});
}
async fn set_ns(&self, ctx: &mut Context<'_>, opt: &mut Options, ns: &str) {
async fn set_ns(&self, ctx: Context, opt: &mut Options, ns: &str) -> Result<Context, Error> {
let mut ctx = MutableContext::unfreeze(ctx)?;
let mut session = ctx.value("session").unwrap_or(&Value::None).clone();
session.put(NS.as_ref(), ns.to_owned().into());
ctx.add_value("session", session);
ctx.add_value("session", session.into());
opt.set_ns(Some(ns.into()));
Ok(ctx.freeze())
}
async fn set_db(&self, ctx: &mut Context<'_>, opt: &mut Options, db: &str) {
async fn set_db(&self, ctx: Context, opt: &mut Options, db: &str) -> Result<Context, Error> {
let mut ctx = MutableContext::unfreeze(ctx)?;
let mut session = ctx.value("session").unwrap_or(&Value::None).clone();
session.put(DB.as_ref(), db.to_owned().into());
ctx.add_value("session", session);
ctx.add_value("session", session.into());
opt.set_db(Some(db.into()));
Ok(ctx.freeze())
}
#[instrument(level = "debug", name = "executor", skip_all)]
pub async fn execute(
&mut self,
mut ctx: Context<'_>,
mut ctx: Context,
opt: Options,
qry: Query,
) -> Result<Vec<Response>, Error> {
@ -273,10 +277,10 @@ impl<'a> Executor<'a> {
// Switch to a different NS or DB
Statement::Use(stm) => {
if let Some(ref ns) = stm.ns {
self.set_ns(&mut ctx, &mut opt, ns).await;
ctx = self.set_ns(ctx, &mut opt, ns).await?;
}
if let Some(ref db) = stm.db {
self.set_db(&mut ctx, &mut opt, db).await;
ctx = self.set_db(ctx, &mut opt, db).await?;
}
Ok(Value::None)
}
@ -291,7 +295,9 @@ impl<'a> Executor<'a> {
// The transaction began successfully
false => {
// ctx.set_transaction(txn)
ctx.set_transaction(self.txn());
let mut c = MutableContext::unfreeze(ctx)?;
c.set_transaction(self.txn());
ctx = c.freeze();
// Check the statement
match stack
.enter(|stk| stm.compute(stk, &ctx, &opt, None))
@ -302,7 +308,9 @@ impl<'a> Executor<'a> {
// Check if writeable
let writeable = stm.writeable();
// Set the parameter
ctx.add_value(stm.name, val);
let mut c = MutableContext::unfreeze(ctx)?;
c.add_value(stm.name, val.into());
ctx = c.freeze();
// Finalise transaction, returning nothing unless it couldn't commit
if writeable {
match self.commit(loc).await {
@ -349,7 +357,7 @@ impl<'a> Executor<'a> {
true => Err(Error::TxFailure),
// The transaction began successfully
false => {
let mut ctx = Context::new(&ctx);
let mut ctx = MutableContext::new(&ctx);
// Process the statement
let res = match stm.timeout() {
// There is a timeout clause
@ -359,11 +367,13 @@ impl<'a> Executor<'a> {
Err(err)
} else {
ctx.set_transaction(self.txn());
let c = ctx.freeze();
// Process the statement
let res = stack
.enter(|stk| stm.compute(stk, &ctx, &opt, None))
.enter(|stk| stm.compute(stk, &c, &opt, None))
.finish()
.await;
ctx = MutableContext::unfreeze(c)?;
// Catch statement timeout
match ctx.is_timedout() {
true => Err(Error::QueryTimedout),
@ -374,10 +384,13 @@ impl<'a> Executor<'a> {
// There is no timeout clause
None => {
ctx.set_transaction(self.txn());
stack
.enter(|stk| stm.compute(stk, &ctx, &opt, None))
let c = ctx.freeze();
let r = stack
.enter(|stk| stm.compute(stk, &c, &opt, None))
.finish()
.await
.await;
ctx = MutableContext::unfreeze(c)?;
r
}
};
// Check if this is a RETURN statement
@ -396,6 +409,7 @@ impl<'a> Executor<'a> {
res => res,
},
};
let ctx = ctx.freeze();
// Finalise transaction and return the result.
if res.is_ok() && stm.writeable() {
if let Err(e) = self.commit(loc).await {

View file

@ -61,7 +61,7 @@ impl GroupsCollector {
pub(super) async fn push(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
obj: Value,
@ -88,7 +88,7 @@ impl GroupsCollector {
async fn pushes(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
agrs: &mut [Aggregator],
idioms: &[Idiom],
@ -108,7 +108,7 @@ impl GroupsCollector {
pub(super) async fn output(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<MemoryCollector, Error> {
@ -256,7 +256,7 @@ impl Aggregator {
async fn push(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
val: Value,
) -> Result<(), Error> {

View file

@ -1,5 +1,5 @@
use crate::ctx::Canceller;
use crate::ctx::Context;
use crate::ctx::{Canceller, MutableContext};
#[cfg(not(target_arch = "wasm32"))]
use crate::dbs::distinct::AsyncDistinct;
use crate::dbs::distinct::SyncDistinct;
@ -20,6 +20,7 @@ use reblessive::tree::Stk;
#[cfg(not(target_arch = "wasm32"))]
use reblessive::TreeStack;
use std::mem;
use std::sync::Arc;
#[derive(Clone)]
pub(crate) enum Iterable {
@ -35,21 +36,21 @@ pub(crate) enum Iterable {
}
pub(crate) struct Processed {
pub(crate) rid: Option<Thing>,
pub(crate) ir: Option<IteratorRecord>,
pub(crate) rid: Option<Arc<Thing>>,
pub(crate) ir: Option<Arc<IteratorRecord>>,
pub(crate) val: Operable,
}
pub(crate) enum Operable {
Value(Value),
Mergeable(Value, Value),
Relatable(Thing, Value, Thing, Option<Value>),
Value(Arc<Value>),
Mergeable(Arc<Value>, Arc<Value>),
Relatable(Thing, Arc<Value>, Thing, Option<Arc<Value>>),
}
pub(crate) enum Workable {
Normal,
Insert(Value),
Relate(Thing, Thing, Option<Value>),
Insert(Arc<Value>),
Relate(Thing, Thing, Option<Arc<Value>>),
}
#[derive(Default)]
@ -96,7 +97,7 @@ impl Iterator {
pub async fn prepare(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
val: Value,
@ -281,15 +282,16 @@ impl Iterator {
pub async fn output(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Log the statement
trace!("Iterating: {}", stm);
// Enable context override
let mut cancel_ctx = Context::new(ctx);
let mut cancel_ctx = MutableContext::new(ctx);
self.run = cancel_ctx.add_cancel();
let mut cancel_ctx = cancel_ctx.freeze();
// Process the query LIMIT clause
self.setup_limit(stk, &cancel_ctx, opt, stm).await?;
// Process the query START clause
@ -313,7 +315,9 @@ impl Iterator {
if let Some(qp) = ctx.get_query_planner() {
while let Some(s) = qp.next_iteration_stage().await {
let is_last = matches!(s, IterationStage::Iterate(_));
cancel_ctx.set_iteration_stage(s);
let mut c = MutableContext::unfreeze(cancel_ctx)?;
c.set_iteration_stage(s);
cancel_ctx = c.freeze();
if !is_last {
self.clone().iterate(stk, &cancel_ctx, opt, stm).await?;
};
@ -366,7 +370,7 @@ impl Iterator {
async fn setup_limit(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -380,7 +384,7 @@ impl Iterator {
async fn setup_start(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -394,7 +398,7 @@ impl Iterator {
async fn output_split(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -438,7 +442,7 @@ impl Iterator {
async fn output_fetch(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -464,7 +468,7 @@ impl Iterator {
async fn iterate(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -484,7 +488,7 @@ impl Iterator {
async fn iterate(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -582,7 +586,7 @@ impl Iterator {
pub async fn process(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
pro: Processed,
@ -597,7 +601,7 @@ impl Iterator {
async fn result(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
res: Result<Value, Error>,

View file

@ -11,7 +11,7 @@ pub(super) struct Plan {
impl Plan {
pub(super) fn new(
ctx: &Context<'_>,
ctx: &Context,
stm: &Statement<'_>,
iterables: &Vec<Iterable>,
results: &Results,
@ -43,7 +43,7 @@ impl Plan {
pub(super) struct Explanation(Vec<ExplainItem>);
impl Explanation {
fn add_iter(&mut self, ctx: &Context<'_>, iter: &Iterable) {
fn add_iter(&mut self, ctx: &Context, iter: &Iterable) {
self.0.push(ExplainItem::new_iter(ctx, iter));
}
@ -87,7 +87,7 @@ impl ExplainItem {
}
}
fn new_iter(ctx: &Context<'_>, iter: &Iterable) -> Self {
fn new_iter(ctx: &Context, iter: &Iterable) -> Self {
match iter {
Iterable::Value(v) => Self {
name: "Iterate Value".into(),

View file

@ -1,5 +1,5 @@
use crate::cnf::NORMAL_FETCH_SIZE;
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
#[cfg(not(target_arch = "wasm32"))]
use crate::dbs::distinct::AsyncDistinct;
use crate::dbs::distinct::SyncDistinct;
@ -22,7 +22,7 @@ impl Iterable {
pub(crate) async fn iterate(
self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
ite: &mut Iterator,
@ -39,7 +39,7 @@ impl Iterable {
pub(crate) async fn channel(
self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
chn: Sender<Processed>,
@ -52,7 +52,7 @@ impl Iterable {
}
}
fn iteration_stage_check(&self, ctx: &Context<'_>) -> bool {
fn iteration_stage_check(&self, ctx: &Context) -> bool {
match self {
Iterable::Table(tb) | Iterable::Index(tb, _) => {
if let Some(IterationStage::BuildKnn) = ctx.get_iteration_stage() {
@ -79,7 +79,7 @@ impl<'a> Processor<'a> {
async fn process(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
pro: Processed,
@ -113,7 +113,7 @@ impl<'a> Processor<'a> {
async fn process_iterable(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
iterable: Iterable,
@ -130,8 +130,9 @@ impl<'a> Processor<'a> {
if let Some(exe) = qp.get_query_executor(&v.0) {
// We set the query executor matching the current table in the Context
// Avoiding search in the hashmap of the query planner for each doc
let mut ctx = Context::new(ctx);
let mut ctx = MutableContext::new(ctx);
ctx.set_query_executor(exe.clone());
let ctx = ctx.freeze();
return self.process_table(stk, &ctx, opt, stm, &v).await;
}
}
@ -142,8 +143,9 @@ impl<'a> Processor<'a> {
if let Some(exe) = qp.get_query_executor(&t.0) {
// We set the query executor matching the current table in the Context
// Avoiding search in the hashmap of the query planner for each doc
let mut ctx = Context::new(ctx);
let mut ctx = MutableContext::new(ctx);
ctx.set_query_executor(exe.clone());
let ctx = ctx.freeze();
return self.process_index(stk, &ctx, opt, stm, &t, irf).await;
}
}
@ -163,7 +165,7 @@ impl<'a> Processor<'a> {
async fn process_value(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
v: Value,
@ -172,7 +174,7 @@ impl<'a> Processor<'a> {
let pro = Processed {
rid: None,
ir: None,
val: Operable::Value(v),
val: Operable::Value(v.into()),
};
// Process the document record
self.process(stk, ctx, opt, stm, pro).await
@ -181,7 +183,7 @@ impl<'a> Processor<'a> {
async fn process_defer(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
v: Thing,
@ -190,9 +192,9 @@ impl<'a> Processor<'a> {
ctx.tx().check_ns_db_tb(opt.ns()?, opt.db()?, &v.tb, opt.strict).await?;
// Process the document record
let pro = Processed {
rid: Some(v),
rid: Some(v.into()),
ir: None,
val: Operable::Value(Value::None),
val: Operable::Value(Value::None.into()),
};
self.process(stk, ctx, opt, stm, pro).await?;
// Everything ok
@ -202,7 +204,7 @@ impl<'a> Processor<'a> {
async fn process_thing(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
v: Thing,
@ -213,13 +215,16 @@ impl<'a> Processor<'a> {
let key = thing::new(opt.ns()?, opt.db()?, &v.tb, &v.id);
let val = ctx.tx().get(key, opt.version).await?;
// Parse the data from the store
let val = Operable::Value(match val {
Some(v) => Value::from(v),
None => Value::None,
});
let val = Operable::Value(
match val {
Some(v) => Value::from(v),
None => Value::None,
}
.into(),
);
// Process the document record
let pro = Processed {
rid: Some(v),
rid: Some(v.into()),
ir: None,
val,
};
@ -231,7 +236,7 @@ impl<'a> Processor<'a> {
async fn process_mergeable(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
(v, o): (Thing, Value),
@ -247,10 +252,10 @@ impl<'a> Processor<'a> {
None => Value::None,
};
// Create a new operable value
let val = Operable::Mergeable(x, o);
let val = Operable::Mergeable(x.into(), o.into());
// Process the document record
let pro = Processed {
rid: Some(v),
rid: Some(v.into()),
ir: None,
val,
};
@ -262,7 +267,7 @@ impl<'a> Processor<'a> {
async fn process_relatable(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
(f, v, w, o): (Thing, Thing, Thing, Option<Value>),
@ -278,10 +283,10 @@ impl<'a> Processor<'a> {
None => Value::None,
};
// Create a new operable value
let val = Operable::Relatable(f, x, w, o);
let val = Operable::Relatable(f, x.into(), w, o.map(|v| v.into()));
// Process the document record
let pro = Processed {
rid: Some(v),
rid: Some(v.into()),
ir: None,
val,
};
@ -293,7 +298,7 @@ impl<'a> Processor<'a> {
async fn process_table(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
v: &Table,
@ -319,10 +324,10 @@ impl<'a> Processor<'a> {
let val: Value = (&v).into();
let rid = Thing::from((key.tb, key.id));
// Create a new operable value
let val = Operable::Value(val);
let val = Operable::Value(val.into());
// Process the record
let pro = Processed {
rid: Some(rid),
rid: Some(rid.into()),
ir: None,
val,
};
@ -335,7 +340,7 @@ impl<'a> Processor<'a> {
async fn process_range(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
v: Range,
@ -378,10 +383,10 @@ impl<'a> Processor<'a> {
let val: Value = (&v).into();
let rid = Thing::from((key.tb, key.id));
// Create a new operable value
let val = Operable::Value(val);
let val = Operable::Value(val.into());
// Process the record
let pro = Processed {
rid: Some(rid),
rid: Some(rid.into()),
ir: None,
val,
};
@ -394,7 +399,7 @@ impl<'a> Processor<'a> {
async fn process_edge(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
e: Edges,
@ -491,12 +496,12 @@ impl<'a> Processor<'a> {
let rid = Thing::from((gra.ft, gra.fk));
// Parse the data from the store
let val = Operable::Value(match val {
Some(v) => Value::from(v),
None => Value::None,
Some(v) => Value::from(v).into(),
None => Value::None.into(),
});
// Process the record
let pro = Processed {
rid: Some(rid),
rid: Some(rid.into()),
ir: None,
val,
};
@ -510,7 +515,7 @@ impl<'a> Processor<'a> {
async fn process_index(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
table: &Table,
@ -550,7 +555,7 @@ impl<'a> Processor<'a> {
}
async fn next_batch(
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
iterator: &mut ThingIterator,
) -> Result<Vec<Processed>, Error> {
@ -564,11 +569,11 @@ impl<'a> Processor<'a> {
v
} else {
// Otherwise we have to fetch the record
Iterable::fetch_thing(&txn, opt, &r.0).await?
Iterable::fetch_thing(&txn, opt, &r.0).await?.into()
};
let p = Processed {
rid: Some(r.0),
ir: Some(r.1),
ir: Some(r.1.into()),
val: Operable::Value(v),
};
to_process.push(p);

View file

@ -39,7 +39,7 @@ impl Results {
feature = "kv-fdb",
feature = "kv-tikv",
))]
ctx: &Context<'_>,
ctx: &Context,
stm: &Statement<'_>,
) -> Result<Self, Error> {
if stm.expr().is_some() && stm.group().is_some() {
@ -63,7 +63,7 @@ impl Results {
pub(super) async fn push(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
val: Value,

View file

@ -1,4 +1,4 @@
use crate::ctx::Context;
use crate::ctx::MutableContext;
use crate::iam::Auth;
use crate::iam::{Level, Role};
use crate::sql::value::Value;
@ -83,16 +83,16 @@ impl Session {
}
/// Convert a session into a runtime
pub(crate) fn context<'a>(&self, mut ctx: Context<'a>) -> Context<'a> {
pub(crate) fn context(&self, ctx: &mut MutableContext) {
// Add access method data
let val: Value = self.ac.to_owned().into();
ctx.add_value("access", val);
ctx.add_value("access", val.into());
// Add record access data
let val: Value = self.rd.to_owned().into();
ctx.add_value("auth", val);
ctx.add_value("auth", val.into());
// Add token data
let val: Value = self.tk.to_owned().into();
ctx.add_value("token", val);
ctx.add_value("token", val.into());
// Add session value
let val: Value = Value::from(map! {
"ac".to_string() => self.ac.to_owned().into(),
@ -105,9 +105,7 @@ impl Session {
"rd".to_string() => self.rd.to_owned().into(),
"tk".to_string() => self.tk.to_owned().into(),
});
ctx.add_value("session", val);
// Output context
ctx
ctx.add_value("session", val.into());
}
/// Create a system session for a given level and role

View file

@ -1,15 +1,16 @@
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
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) {
pub async fn mock<'a>() -> (Context, 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();
let txn = txn.rollback_and_ignore().await.enclose();
let ctx = Context::default().with_transaction(txn);
(ctx, opt)
let mut ctx = MutableContext::default();
ctx.set_transaction(txn);
(ctx.freeze(), opt)
}

View file

@ -1,5 +1,5 @@
use crate::cnf::PROTECTED_PARAM_NAMES;
use crate::ctx::Context;
use crate::ctx::MutableContext;
use crate::err::Error;
use crate::sql::value::Value;
use std::collections::BTreeMap;
@ -7,18 +7,18 @@ use std::collections::BTreeMap;
pub(crate) type Variables = Option<BTreeMap<String, Value>>;
pub(crate) trait Attach {
fn attach(self, ctx: Context) -> Result<Context, Error>;
fn attach(self, ctx: &mut MutableContext) -> Result<(), Error>;
}
impl Attach for Variables {
fn attach(self, mut ctx: Context) -> Result<Context, Error> {
fn attach(self, ctx: &mut MutableContext) -> Result<(), Error> {
match self {
Some(m) => {
for (key, val) in m {
// Check if the variable is a protected variable
match PROTECTED_PARAM_NAMES.contains(&key.as_str()) {
// The variable isn't protected and can be stored
false => ctx.add_value(key, val),
false => ctx.add_value(key, val.into()),
// The user tried to set a protected variable
true => {
return Err(Error::InvalidParam {
@ -27,9 +27,9 @@ impl Attach for Variables {
}
}
}
Ok(ctx)
Ok(())
}
None => Ok(ctx),
None => Ok(()),
}
}
}

View file

@ -6,11 +6,11 @@ use crate::err::Error;
use crate::sql::permission::Permission;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn allow(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {

View file

@ -1,4 +1,4 @@
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::dbs::Workable;
@ -9,11 +9,11 @@ use crate::sql::operator::Operator;
use crate::sql::value::Value;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn alter(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -70,14 +70,16 @@ impl<'a> Document<'a> {
}
Data::UpdateExpression(x) => {
// Duplicate context
let mut ctx = Context::new(ctx);
let mut ctx = MutableContext::new(ctx);
// Add insertable value
if let Workable::Insert(value) = &self.extras {
ctx.add_value("input", value);
ctx.add_value("input", value.clone());
}
if let Workable::Relate(_, _, Some(value)) = &self.extras {
ctx.add_value("input", value);
ctx.add_value("input", value.clone());
}
// Freeze the context
let ctx: Context = ctx.into();
// Process ON DUPLICATE KEY clause
for x in x.iter() {
let v = x.2.compute(stk, &ctx, opt, Some(&self.current)).await?;

View file

@ -4,10 +4,10 @@ use crate::dbs::Statement;
use crate::doc::Document;
use crate::err::Error;
impl<'a> Document<'a> {
impl Document {
pub async fn changefeeds(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {
@ -24,15 +24,17 @@ impl<'a> Document<'a> {
// Check if changefeeds are enabled
if let Some(cf) = db.as_ref().changefeed.as_ref().or(tb.as_ref().changefeed.as_ref()) {
// Create the changefeed entry
txn.lock().await.record_change(
opt.ns()?,
opt.db()?,
tb.name.as_str(),
self.id.unwrap(),
self.initial.doc.clone(),
self.current.doc.clone(),
cf.store_diff,
);
if let Some(id) = &self.id {
txn.lock().await.record_change(
opt.ns()?,
opt.db()?,
tb.name.as_str(),
id.as_ref(),
self.initial.doc.clone(),
self.current.doc.clone(),
cf.store_diff,
);
}
}
// Carry on
Ok(())

View file

@ -6,11 +6,11 @@ use crate::err::Error;
use crate::sql::Cond;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn check(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -19,10 +19,10 @@ impl<'a> Document<'a> {
pub(crate) async fn check_cond(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
cond: Option<&Cond>,
doc: &CursorDoc<'_>,
doc: &CursorDoc,
) -> Result<(), Error> {
// Check where condition
if let Some(cond) = cond {

View file

@ -6,11 +6,11 @@ use crate::err::Error;
use crate::sql::idiom::Idiom;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn clean(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {
@ -26,20 +26,22 @@ impl<'a> Document<'a> {
match fd.flex {
false => {
// Loop over this field in the document
for k in self.current.doc.each(&fd.name).into_iter() {
for k in self.current.doc.as_ref().each(&fd.name).into_iter() {
keys.push(k);
}
}
true => {
// Loop over every field under this field in the document
for k in self.current.doc.every(Some(&fd.name), true, true).into_iter() {
for k in
self.current.doc.as_ref().every(Some(&fd.name), true, true).into_iter()
{
keys.push(k);
}
}
}
}
// Loop over every field in the document
for fd in self.current.doc.every(None, true, true).iter() {
for fd in self.current.doc.as_ref().every(None, true, true).iter() {
if !keys.contains(fd) {
match fd {
fd if fd.is_id() => continue,

View file

@ -8,12 +8,13 @@ use crate::err::Error;
use crate::sql::value::Value;
use channel::Sender;
use reblessive::tree::Stk;
use std::sync::Arc;
impl<'a> Document<'a> {
impl Document {
#[allow(dead_code)]
pub(crate) async fn compute(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
chn: Sender<Result<Value, Error>>,
@ -32,7 +33,7 @@ impl<'a> Document<'a> {
Operable::Relatable(f, v, w, o) => (v, Workable::Relate(f, w, o)),
};
// Setup a new document
let mut doc = Document::new(pro.rid.as_ref(), pro.ir.as_ref(), &ins.0, ins.1);
let mut doc = Document::new(pro.rid, pro.ir, ins.0, ins.1);
// Process the statement
let res = match stm {
Statement::Select(_) => doc.select(stk, ctx, opt, stm).await,
@ -54,12 +55,12 @@ impl<'a> Document<'a> {
let key = crate::key::thing::new(opt.ns()?, opt.db()?, &v.tb, &v.id);
let val = ctx.tx().get(key, None).await?;
// Parse the data from the store
let val = match val {
let val = Arc::new(match val {
Some(v) => Value::from(v),
None => Value::None,
};
});
pro = Processed {
rid: Some(v),
rid: Some(Arc::new(v)),
ir: None,
val: match doc.extras {
Workable::Normal => Operable::Value(val),

View file

@ -6,15 +6,15 @@ use crate::err::Error;
use crate::sql::value::Value;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn create(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check if table has corrent relation status
// Check if table has current relation status
self.relation(ctx, opt, stm).await?;
// Alter record data
self.alter(stk, ctx, opt, stm).await?;

View file

@ -6,11 +6,11 @@ use crate::err::Error;
use crate::sql::value::Value;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn delete(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {

View file

@ -13,114 +13,191 @@ use crate::sql::statements::live::LiveStatement;
use crate::sql::thing::Thing;
use crate::sql::value::Value;
use crate::sql::Base;
use std::borrow::Cow;
use std::fmt::{Debug, Formatter};
use std::mem;
use std::ops::Deref;
use std::sync::Arc;
pub(crate) struct Document<'a> {
pub(super) id: Option<&'a Thing>,
pub(crate) struct Document {
pub(super) id: Option<Arc<Thing>>,
pub(super) extras: Workable,
pub(super) initial: CursorDoc<'a>,
pub(super) current: CursorDoc<'a>,
pub(super) initial: CursorDoc,
pub(super) current: CursorDoc,
}
#[non_exhaustive]
#[cfg_attr(debug_assertions, derive(Debug))]
pub struct CursorDoc<'a> {
pub(crate) rid: Option<&'a Thing>,
pub(crate) ir: Option<&'a IteratorRecord>,
pub(crate) doc: Cow<'a, Value>,
pub struct CursorDoc {
pub(crate) rid: Option<Arc<Thing>>,
pub(crate) ir: Option<Arc<IteratorRecord>>,
pub(crate) doc: CursorValue,
}
impl<'a> CursorDoc<'a> {
pub(crate) fn new(
rid: Option<&'a Thing>,
ir: Option<&'a IteratorRecord>,
doc: Cow<'a, Value>,
#[non_exhaustive]
#[cfg_attr(debug_assertions, derive(Debug))]
#[derive(Clone)]
pub(crate) struct CursorValue {
mutable: Value,
read_only: Option<Arc<Value>>,
}
impl CursorValue {
pub(crate) fn to_mut(&mut self) -> &mut Value {
if let Some(ro) = self.read_only.take() {
self.mutable = ro.as_ref().clone();
}
&mut self.mutable
}
pub(crate) fn as_arc(&mut self) -> Arc<Value> {
match &self.read_only {
None => {
let v = Arc::new(mem::take(&mut self.mutable));
self.read_only = Some(v.clone());
v
}
Some(v) => v.clone(),
}
}
pub(crate) fn as_ref(&self) -> &Value {
if let Some(ro) = &self.read_only {
ro.as_ref()
} else {
&self.mutable
}
}
pub(crate) fn into_owned(self) -> Value {
if let Some(ro) = &self.read_only {
ro.as_ref().clone()
} else {
self.mutable
}
}
}
impl Deref for CursorValue {
type Target = Value;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl CursorDoc {
pub(crate) fn new<T: Into<CursorValue>>(
rid: Option<Arc<Thing>>,
ir: Option<Arc<IteratorRecord>>,
doc: T,
) -> Self {
Self {
rid,
ir,
doc,
doc: doc.into(),
}
}
}
impl<'a> From<&'a Value> for CursorDoc<'a> {
fn from(doc: &'a Value) -> Self {
impl From<Value> for CursorValue {
fn from(value: Value) -> Self {
Self {
mutable: value,
read_only: None,
}
}
}
impl From<Arc<Value>> for CursorValue {
fn from(value: Arc<Value>) -> Self {
Self {
mutable: Value::None,
read_only: Some(value),
}
}
}
impl From<Value> for CursorDoc {
fn from(val: Value) -> Self {
Self {
rid: None,
ir: None,
doc: Cow::Borrowed(doc),
doc: CursorValue {
mutable: val,
read_only: None,
},
}
}
}
impl<'a> From<&'a mut Value> for CursorDoc<'a> {
fn from(doc: &'a mut Value) -> Self {
impl From<Arc<Value>> for CursorDoc {
fn from(doc: Arc<Value>) -> Self {
Self {
rid: None,
ir: None,
doc: Cow::Borrowed(doc),
doc: CursorValue {
mutable: Value::None,
read_only: Some(doc),
},
}
}
}
impl<'a> Debug for Document<'a> {
impl Debug for Document {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Document - id: <{:?}>", self.id)
}
}
impl<'a> From<&Document<'a>> for Vec<u8> {
fn from(val: &Document<'a>) -> Vec<u8> {
impl From<&Document> for Vec<u8> {
fn from(val: &Document) -> Vec<u8> {
val.current.doc.as_ref().into()
}
}
impl<'a> Document<'a> {
impl Document {
pub fn new(
id: Option<&'a Thing>,
ir: Option<&'a IteratorRecord>,
val: &'a Value,
id: Option<Arc<Thing>>,
ir: Option<Arc<IteratorRecord>>,
val: Arc<Value>,
extras: Workable,
) -> Self {
Document {
id,
id: id.clone(),
extras,
current: CursorDoc::new(id, ir, Cow::Borrowed(val)),
initial: CursorDoc::new(id, ir, Cow::Borrowed(val)),
current: CursorDoc::new(id.clone(), ir.clone(), val.clone()),
initial: CursorDoc::new(id, ir, val),
}
}
/// Get the current document, as it is being modified
#[allow(unused)]
pub(crate) fn current_doc(&self) -> &Value {
self.current.doc.as_ref()
&self.current.doc
}
/// Get the initial version of the document before it is modified
#[allow(unused)]
pub(crate) fn initial_doc(&self) -> &Value {
self.initial.doc.as_ref()
&self.initial.doc
}
}
impl<'a> Document<'a> {
impl Document {
/// Check if document has changed
pub fn changed(&self) -> bool {
self.initial.doc != self.current.doc
self.initial.doc.as_ref() != self.current.doc.as_ref()
}
/// Check if document is being created
pub fn is_new(&self) -> bool {
self.initial.doc.is_none() && self.current.doc.is_some()
self.initial.doc.as_ref().is_none() && self.current.doc.as_ref().is_some()
}
/// Get the table for this document
pub async fn tb(
&self,
ctx: &Context<'a>,
ctx: &Context,
opt: &Options,
) -> Result<Arc<DefineTableStatement>, Error> {
// Get transaction
@ -149,7 +226,7 @@ impl<'a> Document<'a> {
/// Get the foreign tables for this document
pub async fn ft(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
) -> Result<Arc<[DefineTableStatement]>, Error> {
// Get the record id
@ -160,7 +237,7 @@ impl<'a> Document<'a> {
/// Get the events for this document
pub async fn ev(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
) -> Result<Arc<[DefineEventStatement]>, Error> {
// Get the record id
@ -171,7 +248,7 @@ impl<'a> Document<'a> {
/// Get the fields for this document
pub async fn fd(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
) -> Result<Arc<[DefineFieldStatement]>, Error> {
// Get the record id
@ -182,7 +259,7 @@ impl<'a> Document<'a> {
/// Get the indexes for this document
pub async fn ix(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
) -> Result<Arc<[DefineIndexStatement]>, Error> {
// Get the record id
@ -191,11 +268,7 @@ impl<'a> Document<'a> {
ctx.tx().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,
) -> Result<Arc<[LiveStatement]>, Error> {
pub async fn lv(&self, ctx: &Context, opt: &Options) -> Result<Arc<[LiveStatement]>, Error> {
// Get the record id
let id = self.id.as_ref().unwrap();
// Get the table definition

View file

@ -10,10 +10,10 @@ use crate::sql::paths::OUT;
use crate::sql::value::Value;
use crate::sql::Dir;
impl<'a> Document<'a> {
impl Document {
pub async fn edges(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {

View file

@ -4,17 +4,17 @@ use crate::dbs::Statement;
use crate::doc::Document;
use crate::err::Error;
impl<'a> Document<'a> {
impl Document {
pub async fn empty(
&self,
_ctx: &Context<'_>,
_ctx: &Context,
_opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Check if this record exists
if self.id.is_some() {
// There is no current record
if self.current.doc.is_none() {
if self.current.doc.as_ref().is_none() {
// Ignore this requested record
return Err(Error::Ignore);
}

View file

@ -4,10 +4,10 @@ use crate::dbs::Statement;
use crate::doc::Document;
use crate::err::Error;
impl<'a> Document<'a> {
impl Document {
pub async fn erase(
&mut self,
_ctx: &Context<'_>,
_ctx: &Context,
_opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {

View file

@ -1,17 +1,16 @@
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::doc::Document;
use crate::err::Error;
use crate::sql::value::Value;
use reblessive::tree::Stk;
use std::ops::Deref;
impl<'a> Document<'a> {
impl Document {
pub async fn event(
&self,
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -35,17 +34,21 @@ impl<'a> Document<'a> {
} else {
Value::from("UPDATE")
};
let after = self.current.doc.as_arc();
let before = self.initial.doc.as_arc();
// Depending on type of event, how do we populate the document
let doc = match stm.is_delete() {
true => &self.initial,
false => &self.current,
true => &mut self.initial,
false => &mut self.current,
};
// Configure the context
let mut ctx = Context::new(ctx);
ctx.add_value("event", evt);
ctx.add_value("value", doc.doc.deref());
ctx.add_value("after", self.current.doc.deref());
ctx.add_value("before", self.initial.doc.deref());
let mut ctx = MutableContext::new(ctx);
ctx.add_value("event", evt.into());
ctx.add_value("value", doc.doc.as_arc());
ctx.add_value("after", after);
ctx.add_value("before", before);
// Freeze the context
let ctx = ctx.freeze();
// Process conditional clause
let val = ev.when.compute(stk, &ctx, opt, Some(doc)).await?;
// Execute event if value is truthy

View file

@ -1,4 +1,4 @@
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::doc::Document;
@ -8,12 +8,13 @@ use crate::sql::permission::Permission;
use crate::sql::value::Value;
use crate::sql::Kind;
use reblessive::tree::Stk;
use std::sync::Arc;
impl<'a> Document<'a> {
impl Document {
pub async fn field(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {
@ -24,17 +25,17 @@ impl<'a> Document<'a> {
// Get the record id
let rid = self.id.as_ref().unwrap();
// Get the user applied input
let inp = self.initial.doc.changed(self.current.doc.as_ref());
let inp = self.initial.doc.as_ref().changed(self.current.doc.as_ref());
// Loop through all field statements
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() {
for (k, mut val) in self.current.doc.as_ref().walk(&fd.name).into_iter() {
// Get the initial value
let old = self.initial.doc.pick(&k);
let old = Arc::new(self.initial.doc.as_ref().pick(&k));
// Get the input value
let inp = inp.pick(&k);
let inp = Arc::new(inp.pick(&k));
// Check for READONLY clause
if fd.readonly && !self.is_new() && val != old {
if fd.readonly && !self.is_new() && val.ne(&old) {
return Err(Error::FieldReadonly {
field: fd.name.clone(),
thing: rid.to_string(),
@ -52,11 +53,13 @@ impl<'a> Document<'a> {
if let Some(expr) = def {
if self.is_new() && val.is_none() {
// Configure the context
let mut ctx = Context::new(ctx);
ctx.add_value("input", &inp);
ctx.add_value("value", &val);
ctx.add_value("after", &val);
ctx.add_value("before", &old);
let mut ctx = MutableContext::new(ctx);
let v = Arc::new(val);
ctx.add_value("input", inp.clone());
ctx.add_value("value", v.clone());
ctx.add_value("after", v);
ctx.add_value("before", old.clone());
let ctx = ctx.freeze();
// Process the VALUE clause
val = expr.compute(stk, &ctx, opt, Some(&self.current)).await?;
}
@ -83,11 +86,13 @@ impl<'a> Document<'a> {
// Only run value clause for mutable and new fields
if !fd.readonly || self.is_new() {
// Configure the context
let mut ctx = Context::new(ctx);
ctx.add_value("input", &inp);
ctx.add_value("value", &val);
ctx.add_value("after", &val);
ctx.add_value("before", &old);
let v = Arc::new(val);
let mut ctx = MutableContext::new(ctx);
ctx.add_value("input", inp.clone());
ctx.add_value("value", v.clone());
ctx.add_value("after", v);
ctx.add_value("before", old.clone());
let ctx = ctx.freeze();
// Process the VALUE clause
val = expr.compute(stk, &ctx, opt, Some(&self.current)).await?;
}
@ -119,11 +124,13 @@ impl<'a> Document<'a> {
// Otherwise let's process the ASSERT clause
_ => {
// Configure the context
let mut ctx = Context::new(ctx);
ctx.add_value("input", &inp);
ctx.add_value("value", &val);
ctx.add_value("after", &val);
ctx.add_value("before", &old);
let mut ctx = MutableContext::new(ctx);
let v = Arc::new(val.clone());
ctx.add_value("input", inp.clone());
ctx.add_value("value", v.clone());
ctx.add_value("after", v);
ctx.add_value("before", old.clone());
let ctx = ctx.freeze();
// Process the ASSERT clause
if !expr.compute(stk, &ctx, opt, Some(&self.current)).await?.is_truthy()
{
@ -154,7 +161,7 @@ impl<'a> Document<'a> {
// The field PERMISSIONS clause
// is NONE, meaning that this
// change will be reverted.
Permission::None => val = old,
Permission::None => val = old.as_ref().clone(),
// The field PERMISSIONS clause
// is a custom expression, so
// we check the expression and
@ -163,14 +170,16 @@ impl<'a> Document<'a> {
// Disable permissions
let opt = &opt.new_with_perms(false);
// Configure the context
let mut ctx = Context::new(ctx);
ctx.add_value("input", &inp);
ctx.add_value("value", &val);
ctx.add_value("after", &val);
ctx.add_value("before", &old);
let mut ctx = MutableContext::new(ctx);
let v = Arc::new(val.clone());
ctx.add_value("input", inp);
ctx.add_value("value", v.clone());
ctx.add_value("after", v);
ctx.add_value("before", old.clone());
let ctx = ctx.freeze();
// Process the PERMISSION clause
if !e.compute(stk, &ctx, opt, Some(&self.current)).await?.is_truthy() {
val = old
val = old.as_ref().clone()
}
}
}
@ -178,7 +187,7 @@ impl<'a> Document<'a> {
// Set the value of the field
match val {
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?,
v => self.current.doc.to_mut().set(stk, ctx, opt, &k, v).await?,
};
}
}

View file

@ -14,11 +14,11 @@ use crate::sql::statements::DefineIndexStatement;
use crate::sql::{Part, Thing, Value};
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn index(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {
@ -27,7 +27,9 @@ impl<'a> Document<'a> {
// Collect indexes or skip
let ixs = match &opt.force {
Force::Index(ix)
if ix.first().is_some_and(|ix| self.id.is_some_and(|id| ix.what.0 == id.tb)) =>
if ix
.first()
.is_some_and(|ix| self.id.as_ref().is_some_and(|id| ix.what.0 == id.tb)) =>
{
ix.clone()
}
@ -75,12 +77,12 @@ impl<'a> Document<'a> {
/// It will return: ["Tobie", "piano"]
async fn build_opt_values(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
ix: &DefineIndexStatement,
doc: &CursorDoc<'_>,
doc: &CursorDoc,
) -> Result<Option<Vec<Value>>, Error> {
if !doc.doc.is_some() {
if !doc.doc.as_ref().is_some() {
return Ok(None);
}
let mut o = Vec::with_capacity(ix.cols.len());
@ -279,7 +281,7 @@ impl<'a> IndexOperation<'a> {
))
}
async fn index_unique(&mut self, ctx: &Context<'_>) -> Result<(), Error> {
async fn index_unique(&mut self, ctx: &Context) -> Result<(), Error> {
// Get the transaction
let txn = ctx.tx();
// Lock the transaction
@ -314,7 +316,7 @@ impl<'a> IndexOperation<'a> {
Ok(())
}
async fn index_non_unique(&mut self, ctx: &Context<'_>) -> Result<(), Error> {
async fn index_non_unique(&mut self, ctx: &Context) -> Result<(), Error> {
// Get the transaction
let txn = ctx.tx();
// Lock the transaction
@ -361,7 +363,7 @@ impl<'a> IndexOperation<'a> {
async fn index_full_text(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
p: &SearchParams,
) -> Result<(), Error> {
let ikb = IndexKeyBase::new(self.opt.ns()?, self.opt.db()?, self.ix)?;
@ -379,7 +381,7 @@ impl<'a> IndexOperation<'a> {
async fn index_mtree(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
p: &MTreeParams,
) -> Result<(), Error> {
let txn = ctx.tx();
@ -397,7 +399,7 @@ impl<'a> IndexOperation<'a> {
mt.finish(&txn).await
}
async fn index_hnsw(&mut self, ctx: &Context<'_>, p: &HnswParams) -> Result<(), Error> {
async fn index_hnsw(&mut self, ctx: &Context, p: &HnswParams) -> Result<(), Error> {
let hnsw = ctx.get_index_stores().get_index_hnsw(self.opt, self.ix, p).await?;
let mut hnsw = hnsw.write().await;
// Delete the old index data

View file

@ -6,16 +6,16 @@ use crate::err::Error;
use crate::sql::value::Value;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn insert(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check whether current record exists
match self.current.doc.is_some() {
match self.current.doc.as_ref().is_some() {
// 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.
@ -48,7 +48,7 @@ impl<'a> Document<'a> {
async fn insert_create(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {
@ -86,7 +86,7 @@ impl<'a> Document<'a> {
async fn insert_update(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {

View file

@ -1,4 +1,4 @@
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
use crate::dbs::Action;
use crate::dbs::Notification;
use crate::dbs::Options;
@ -13,14 +13,13 @@ use crate::sql::paths::TK;
use crate::sql::permission::Permission;
use crate::sql::Value;
use reblessive::tree::Stk;
use std::ops::Deref;
use std::sync::Arc;
impl<'a> Document<'a> {
impl Document {
pub async fn lives(
&self,
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -48,6 +47,8 @@ impl<'a> Document<'a> {
} else {
Value::from("UPDATE")
};
let current = self.current.doc.as_arc();
let initial = self.initial.doc.as_arc();
// Check if this is a delete statement
let doc = match stm.is_delete() {
true => &self.initial,
@ -67,7 +68,7 @@ impl<'a> Document<'a> {
// use for processing this LIVE query statement.
// This ensures that we are using the session
// of the user who created the LIVE query.
let mut lqctx = Context::background();
let mut lqctx = MutableContext::background();
// Set the current transaction on the new LIVE
// query context to prevent unreachable behaviour
// and ensure that queries can be executed.
@ -75,17 +76,17 @@ impl<'a> Document<'a> {
// Add the session params to this LIVE query, so
// that queries can use these within field
// projections and WHERE clauses.
lqctx.add_value("access", sess.pick(AC.as_ref()));
lqctx.add_value("auth", sess.pick(RD.as_ref()));
lqctx.add_value("token", sess.pick(TK.as_ref()));
lqctx.add_value("session", sess);
lqctx.add_value("access", sess.pick(AC.as_ref()).into());
lqctx.add_value("auth", sess.pick(RD.as_ref()).into());
lqctx.add_value("token", sess.pick(TK.as_ref()).into());
lqctx.add_value("session", sess.clone().into());
// Add $before, $after, $value, and $event params
// to this LIVE query so the user can use these
// within field projections and WHERE clauses.
lqctx.add_value("event", met);
lqctx.add_value("value", self.current.doc.deref());
lqctx.add_value("after", self.current.doc.deref());
lqctx.add_value("before", self.initial.doc.deref());
lqctx.add_value("event", met.into());
lqctx.add_value("value", current.clone());
lqctx.add_value("after", current);
lqctx.add_value("before", initial);
// We need to create a new options which we will
// use for processing this LIVE query statement.
// This ensures that we are using the auth data
@ -94,6 +95,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.
let lqctx = lqctx.freeze();
match self.lq_check(stk, &lqctx, &lqopt, &lq, doc).await {
Err(Error::Ignore) => continue,
Err(e) => return Err(e),
@ -122,7 +124,7 @@ 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, Some(doc)).await?;
doc.doc.as_ref().compute(stk, &lqctx, lqopt, Some(doc)).await?;
// Remove metadata fields on output
value.del(stk, &lqctx, lqopt, &*META).await?;
// Output result
@ -167,10 +169,10 @@ impl<'a> Document<'a> {
async fn lq_check(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
doc: &CursorDoc<'_>,
doc: &CursorDoc,
) -> Result<(), Error> {
// Check where condition
if let Some(cond) = stm.conds() {
@ -187,10 +189,10 @@ impl<'a> Document<'a> {
async fn lq_allow(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
doc: &CursorDoc<'_>,
doc: &CursorDoc,
) -> Result<(), Error> {
// Should we run permissions checks?
if opt.check_perms(stm.into())? {

View file

@ -6,11 +6,11 @@ use crate::doc::Document;
use crate::err::Error;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn merge(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {

View file

@ -1,4 +1,4 @@
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
use crate::dbs::Options;
use crate::dbs::Statement;
use crate::doc::Document;
@ -10,15 +10,16 @@ use crate::sql::paths::META;
use crate::sql::permission::Permission;
use crate::sql::value::Value;
use reblessive::tree::Stk;
use std::sync::Arc;
impl<'a> Document<'a> {
impl Document {
/// Evaluates a doc that has been modified so that it can be further computed into a result Value
/// This includes some permissions handling, output format handling (as specified in statement),
/// field handling (like params, links etc).
pub async fn pluck(
&self,
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {
@ -31,47 +32,58 @@ impl<'a> Document<'a> {
Output::Null => Ok(Value::Null),
Output::Diff => {
// Output a DIFF of any changes applied to the document
Ok(self.initial.doc.diff(self.current.doc.as_ref(), Idiom::default()).into())
Ok(self
.initial
.doc
.as_ref()
.diff(self.current.doc.as_ref(), Idiom::default())
.into())
}
Output::After => {
// Output the full document after all changes were applied
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
self.current.doc.as_ref().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, Some(&self.initial)).await
self.initial.doc.as_ref().compute(stk, ctx, opt, Some(&self.initial)).await
}
Output::Fields(v) => {
// Configure the context
let mut ctx = Context::new(ctx);
ctx.add_value("after", self.current.doc.as_ref());
ctx.add_value("before", self.initial.doc.as_ref());
let mut ctx = MutableContext::new(ctx);
ctx.add_value("after", self.current.doc.as_arc());
ctx.add_value("before", self.initial.doc.as_arc());
let ctx = ctx.freeze();
// Output the specified fields
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()),
0 => Ok(self
.initial
.doc
.as_ref()
.diff(self.current.doc.as_ref(), Idiom::default())
.into()),
_ => s.expr.compute(stk, ctx, opt, Some(&self.current), false).await,
},
Statement::Select(s) => {
s.expr.compute(stk, ctx, opt, Some(&self.current), s.group.is_some()).await
}
Statement::Create(_) => {
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
self.current.doc.as_ref().compute(stk, ctx, opt, Some(&self.current)).await
}
Statement::Upsert(_) => {
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
self.current.doc.as_ref().compute(stk, ctx, opt, Some(&self.current)).await
}
Statement::Update(_) => {
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
self.current.doc.as_ref().compute(stk, ctx, opt, Some(&self.current)).await
}
Statement::Relate(_) => {
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
self.current.doc.as_ref().compute(stk, ctx, opt, Some(&self.current)).await
}
Statement::Insert(_) => {
self.current.doc.compute(stk, ctx, opt, Some(&self.current)).await
self.current.doc.as_ref().compute(stk, ctx, opt, Some(&self.current)).await
}
_ => Err(Error::Ignore),
},
@ -92,10 +104,11 @@ impl<'a> Document<'a> {
// Disable permissions
let opt = &opt.new_with_perms(false);
// Get the current value
let val = self.current.doc.pick(k);
let val = Arc::new(self.current.doc.as_ref().pick(k));
// Configure the context
let mut ctx = Context::new(ctx);
ctx.add_value("value", &val);
let mut ctx = MutableContext::new(ctx);
ctx.add_value("value", val);
let ctx = ctx.freeze();
// Process the PERMISSION clause
if !e
.compute(stk, &ctx, opt, Some(&self.current))

View file

@ -7,12 +7,13 @@ use crate::doc::Document;
use crate::err::Error;
use crate::sql::value::Value;
use reblessive::tree::Stk;
use std::sync::Arc;
impl<'a> Document<'a> {
impl Document {
#[allow(dead_code)]
pub(crate) async fn process(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
mut pro: Processed,
@ -26,7 +27,7 @@ impl<'a> Document<'a> {
Operable::Relatable(f, v, w, o) => (v, Workable::Relate(f, w, o)),
};
// Setup a new document
let mut doc = Document::new(pro.rid.as_ref(), pro.ir.as_ref(), &ins.0, ins.1);
let mut doc = Document::new(pro.rid, pro.ir, ins.0, ins.1);
// Process the statement
let res = match stm {
Statement::Select(_) => doc.select(stk, ctx, opt, stm).await,
@ -48,12 +49,12 @@ impl<'a> Document<'a> {
let key = crate::key::thing::new(opt.ns()?, opt.db()?, &v.tb, &v.id);
let val = ctx.tx().get(key, None).await?;
// Parse the data from the store
let val = match val {
let val = Arc::new(match val {
Some(v) => Value::from(v),
None => Value::None,
};
});
pro = Processed {
rid: Some(v),
rid: Some(Arc::new(v)),
ir: None,
val: match doc.extras {
Workable::Normal => Operable::Value(val),

View file

@ -13,11 +13,11 @@ use crate::sql::table::Tables;
use crate::sql::value::{Value, Values};
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn purge(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {
@ -30,15 +30,15 @@ impl<'a> Document<'a> {
// Lock the transaction
let mut txn = txn.lock().await;
// Get the record id
if let Some(rid) = self.id {
if let Some(rid) = &self.id {
// Purge the record data
let key = crate::key::thing::new(opt.ns()?, opt.db()?, &rid.tb, &rid.id);
txn.del(key).await?;
// Purge the record edges
match (
self.initial.doc.pick(&*EDGE),
self.initial.doc.pick(&*IN),
self.initial.doc.pick(&*OUT),
self.initial.doc.as_ref().pick(&*EDGE),
self.initial.doc.as_ref().pick(&*IN),
self.initial.doc.as_ref().pick(&*OUT),
) {
(Value::Bool(true), Value::Thing(ref l), Value::Thing(ref r)) => {
// Get temporary edge references
@ -63,7 +63,7 @@ impl<'a> Document<'a> {
let stm = DeleteStatement {
what: Values(vec![Value::from(Edges {
dir: Dir::Both,
from: rid.clone(),
from: rid.as_ref().clone(),
what: Tables::default(),
})]),
..DeleteStatement::default()

View file

@ -6,18 +6,18 @@ use crate::err::Error;
use crate::sql::value::Value;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn relate(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {
// Check if table has correct relation status
self.relation(ctx, opt, stm).await?;
// Check whether current record exists
match self.current.doc.is_some() {
match self.current.doc.as_ref().is_some() {
// We attempted to RELATE a document with an ID,
// and this ID already exists in the database,
// so we need to update the record instead.
@ -33,7 +33,7 @@ impl<'a> Document<'a> {
async fn relate_create(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {
@ -69,7 +69,7 @@ impl<'a> Document<'a> {
async fn relate_update(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {

View file

@ -4,10 +4,10 @@ use crate::dbs::{Statement, Workable};
use crate::doc::Document;
use crate::err::Error;
impl<'a> Document<'a> {
impl Document {
pub async fn relation(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {

View file

@ -9,10 +9,10 @@ use crate::sql::paths::IN;
use crate::sql::paths::OUT;
use crate::sql::value::Value;
impl<'a> Document<'a> {
impl Document {
pub async fn reset(
&mut self,
_ctx: &Context<'_>,
_ctx: &Context,
_opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {
@ -27,10 +27,10 @@ impl<'a> Document<'a> {
self.current.doc.to_mut().put(&*OUT, r.clone().into());
}
// This is an UPDATE of a graph edge, so reset fields
if self.initial.doc.pick(&*EDGE).is_true() {
if self.initial.doc.as_ref().pick(&*EDGE).is_true() {
self.current.doc.to_mut().put(&*EDGE, Value::Bool(true));
self.current.doc.to_mut().put(&*IN, self.initial.doc.pick(&*IN));
self.current.doc.to_mut().put(&*OUT, self.initial.doc.pick(&*OUT));
self.current.doc.to_mut().put(&*IN, self.initial.doc.as_ref().pick(&*IN));
self.current.doc.to_mut().put(&*OUT, self.initial.doc.as_ref().pick(&*OUT));
}
// Carry on
Ok(())

View file

@ -6,11 +6,11 @@ use crate::err::Error;
use crate::sql::value::Value;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn select(
&self,
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {

View file

@ -4,10 +4,10 @@ use crate::dbs::Statement;
use crate::doc::Document;
use crate::err::Error;
impl<'a> Document<'a> {
impl Document {
pub async fn store(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {

View file

@ -43,14 +43,14 @@ struct FieldDataContext<'a> {
view: &'a View,
groups: &'a Groups,
group_ids: Vec<Value>,
doc: &'a CursorDoc<'a>,
doc: &'a CursorDoc,
}
impl<'a> Document<'a> {
impl Document {
pub async fn table(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<(), Error> {
@ -65,7 +65,7 @@ impl<'a> Document<'a> {
Force::Table(tb)
if tb.first().is_some_and(|tb| {
tb.view.as_ref().is_some_and(|v| {
self.id.is_some_and(|id| v.what.iter().any(|p| p.0 == id.tb))
self.id.as_ref().is_some_and(|id| v.what.iter().any(|p| p.0 == id.tb))
})
}) =>
{
@ -277,10 +277,10 @@ impl<'a> Document<'a> {
async fn get_group_ids(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
group: &Groups,
doc: &CursorDoc<'_>,
doc: &CursorDoc,
) -> Result<Vec<Value>, Error> {
Ok(stk
.scope(|scope| {
@ -297,7 +297,7 @@ impl<'a> Document<'a> {
async fn full(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
exp: &Fields,
) -> Result<Data, Error> {
@ -309,7 +309,7 @@ impl<'a> Document<'a> {
async fn data(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
fdc: FieldDataContext<'_>,
) -> Result<(), Error> {
@ -363,7 +363,7 @@ impl<'a> Document<'a> {
async fn fields(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
fdc: &FieldDataContext<'_>,
) -> Result<(Ops, Ops), Error> {
@ -441,7 +441,7 @@ impl<'a> Document<'a> {
&self,
set_ops: &mut Ops,
del_ops: &mut Ops,
fdc: &FieldDataContext<'_>,
fdc: &FieldDataContext,
field: &Field,
key: Idiom,
val: Value,
@ -487,7 +487,7 @@ impl<'a> Document<'a> {
&self,
set_ops: &mut Ops,
del_ops: &mut Ops,
fdc: &FieldDataContext<'_>,
fdc: &FieldDataContext,
field: &Field,
key: Idiom,
val: Value,
@ -531,12 +531,7 @@ impl<'a> Document<'a> {
}
/// Recomputes the value for one group
fn one_group_query(
fdc: &FieldDataContext<'_>,
field: &Field,
key: &Idiom,
val: Value,
) -> Value {
fn one_group_query(fdc: &FieldDataContext, field: &Field, key: &Idiom, val: Value) -> Value {
// Build the condition merging the optional user provided condition and the group
let mut iter = fdc.groups.0.iter().enumerate();
let cond = if let Some((i, g)) = iter.next() {

View file

@ -6,11 +6,11 @@ use crate::err::Error;
use crate::sql::value::Value;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn update(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {

View file

@ -6,11 +6,11 @@ use crate::err::Error;
use crate::sql::value::Value;
use reblessive::tree::Stk;
impl<'a> Document<'a> {
impl Document {
pub async fn upsert(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stm: &Statement<'_>,
) -> Result<Value, Error> {

View file

@ -64,7 +64,7 @@ where
{
type Output = Result<Vec<F::Ok>, F::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let mut this = self.project();
Poll::Ready(Ok(loop {
match ready!(this.active.as_mut().try_poll_next(cx)?) {
@ -105,7 +105,7 @@ mod tests {
fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
cx: &mut std::task::Context,
) -> std::task::Poll<Self::Output> {
let me = self.project();
ready!(me.sleep.poll(cx));

View file

@ -353,7 +353,7 @@ pub fn logical_xor((lh, rh): (Array, Array)) -> Result<Value, Error> {
}
pub async fn map(
(stk, ctx, opt, doc): (&mut Stk, &Context<'_>, &Options, Option<&CursorDoc<'_>>),
(stk, ctx, opt, doc): (&mut Stk, &Context, &Options, Option<&CursorDoc>),
(array, mapper): (Array, Closure),
) -> Result<Value, Error> {
let mut array = array;

View file

@ -3,18 +3,18 @@ use crate::err::Error;
use crate::sql::value::Value;
#[cfg(not(feature = "http"))]
pub async fn head(_: &Context<'_>, (_, _): (Value, Option<Value>)) -> Result<Value, Error> {
pub async fn head(_: &Context, (_, _): (Value, Option<Value>)) -> Result<Value, Error> {
Err(Error::HttpDisabled)
}
#[cfg(not(feature = "http"))]
pub async fn get(_: &Context<'_>, (_, _): (Value, Option<Value>)) -> Result<Value, Error> {
pub async fn get(_: &Context, (_, _): (Value, Option<Value>)) -> Result<Value, Error> {
Err(Error::HttpDisabled)
}
#[cfg(not(feature = "http"))]
pub async fn put(
_: &Context<'_>,
_: &Context,
(_, _, _): (Value, Option<Value>, Option<Value>),
) -> Result<Value, Error> {
Err(Error::HttpDisabled)
@ -22,7 +22,7 @@ pub async fn put(
#[cfg(not(feature = "http"))]
pub async fn post(
_: &Context<'_>,
_: &Context,
(_, _, _): (Value, Option<Value>, Option<Value>),
) -> Result<Value, Error> {
Err(Error::HttpDisabled)
@ -30,14 +30,14 @@ pub async fn post(
#[cfg(not(feature = "http"))]
pub async fn patch(
_: &Context<'_>,
_: &Context,
(_, _, _): (Value, Option<Value>, Option<Value>),
) -> Result<Value, Error> {
Err(Error::HttpDisabled)
}
#[cfg(not(feature = "http"))]
pub async fn delete(_: &Context<'_>, (_, _): (Value, Option<Value>)) -> Result<Value, Error> {
pub async fn delete(_: &Context, (_, _): (Value, Option<Value>)) -> Result<Value, Error> {
Err(Error::HttpDisabled)
}
@ -71,14 +71,14 @@ fn try_as_opts(
}
#[cfg(feature = "http")]
pub async fn head(ctx: &Context<'_>, (uri, opts): (Value, Option<Value>)) -> Result<Value, Error> {
pub async fn head(ctx: &Context, (uri, opts): (Value, Option<Value>)) -> Result<Value, Error> {
let uri = try_as_uri("http::head", uri)?;
let opts = try_as_opts("http::head", "The second argument should be an object.", opts)?;
crate::fnc::util::http::head(ctx, uri, opts).await
}
#[cfg(feature = "http")]
pub async fn get(ctx: &Context<'_>, (uri, opts): (Value, Option<Value>)) -> Result<Value, Error> {
pub async fn get(ctx: &Context, (uri, opts): (Value, Option<Value>)) -> Result<Value, Error> {
let uri = try_as_uri("http::get", uri)?;
let opts = try_as_opts("http::get", "The second argument should be an object.", opts)?;
crate::fnc::util::http::get(ctx, uri, opts).await
@ -86,7 +86,7 @@ pub async fn get(ctx: &Context<'_>, (uri, opts): (Value, Option<Value>)) -> Resu
#[cfg(feature = "http")]
pub async fn put(
ctx: &Context<'_>,
ctx: &Context,
(uri, body, opts): (Value, Option<Value>, Option<Value>),
) -> Result<Value, Error> {
let uri = try_as_uri("http::put", uri)?;
@ -96,7 +96,7 @@ pub async fn put(
#[cfg(feature = "http")]
pub async fn post(
ctx: &Context<'_>,
ctx: &Context,
(uri, body, opts): (Value, Option<Value>, Option<Value>),
) -> Result<Value, Error> {
let uri = try_as_uri("http::post", uri)?;
@ -106,7 +106,7 @@ pub async fn post(
#[cfg(feature = "http")]
pub async fn patch(
ctx: &Context<'_>,
ctx: &Context,
(uri, body, opts): (Value, Option<Value>, Option<Value>),
) -> Result<Value, Error> {
let uri = try_as_uri("http::patch", uri)?;
@ -115,10 +115,7 @@ pub async fn patch(
}
#[cfg(feature = "http")]
pub async fn delete(
ctx: &Context<'_>,
(uri, opts): (Value, Option<Value>),
) -> Result<Value, Error> {
pub async fn delete(ctx: &Context, (uri, opts): (Value, Option<Value>)) -> Result<Value, Error> {
let uri = try_as_uri("http::delete", uri)?;
let opts = try_as_opts("http::delete", "The second argument should be an object.", opts)?;
crate::fnc::util::http::delete(ctx, uri, opts).await

View file

@ -38,9 +38,9 @@ pub mod vector;
/// Attempts to run any function
pub async fn run(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
name: &str,
args: Vec<Value>,
) -> Result<Value, Error> {
@ -88,8 +88,8 @@ macro_rules! dispatch {
/// Attempts to run any synchronous function.
pub fn synchronous(
ctx: &Context<'_>,
doc: Option<&CursorDoc<'_>>,
ctx: &Context,
doc: Option<&CursorDoc>,
name: &str,
args: Vec<Value>,
) -> Result<Value, Error> {
@ -419,9 +419,9 @@ pub fn synchronous(
/// Attempts to run any synchronous function.
pub async fn idiom(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
value: Value,
name: &str,
args: Vec<Value>,
@ -712,9 +712,9 @@ pub async fn idiom(
/// Attempts to run any asynchronous function.
pub async fn asynchronous(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
name: &str,
args: Vec<Value>,
) -> Result<Value, Error> {
@ -769,11 +769,11 @@ pub async fn asynchronous(
}
fn get_execution_context<'a>(
ctx: &'a Context<'_>,
doc: Option<&'a CursorDoc<'_>>,
) -> Option<(&'a QueryExecutor, &'a CursorDoc<'a>, &'a Thing)> {
ctx: &'a Context,
doc: Option<&'a CursorDoc>,
) -> Option<(&'a QueryExecutor, &'a CursorDoc, &'a Thing)> {
if let Some(doc) = doc {
if let Some(thg) = doc.rid {
if let Some(thg) = &doc.rid {
if let Some(pla) = ctx.get_query_planner() {
if let Some(exe) = pla.get_query_executor(&thg.tb) {
return Some((exe, doc, thg));

View file

@ -175,13 +175,13 @@ enum ExecutorOption<'a> {
}
fn get_executor_and_thing<'a>(
ctx: &'a Context<'_>,
ctx: &'a Context,
doc: &'a CursorDoc,
) -> Option<(&'a QueryExecutor, &'a Thing)> {
if let Some(thg) = doc.rid {
if let Some(thg) = &doc.rid {
if let Some(exe) = ctx.get_query_executor() {
if exe.is_table(&thg.tb) {
return Some((exe, thg));
return Some((exe, thg.as_ref()));
}
}
if let Some(pla) = ctx.get_query_planner() {
@ -194,13 +194,13 @@ fn get_executor_and_thing<'a>(
}
fn get_executor_option<'a>(
ctx: &'a Context<'_>,
doc: Option<&'a CursorDoc<'_>>,
ctx: &'a Context,
doc: Option<&'a CursorDoc>,
exp: &'a Expression,
) -> ExecutorOption<'a> {
if let Some(doc) = doc {
if let Some((exe, thg)) = get_executor_and_thing(ctx, doc) {
if let Some(ir) = doc.ir {
if let Some(ir) = &doc.ir {
if exe.is_iterator_expression(ir.irf(), exp) {
return ExecutorOption::PreMatch;
}
@ -213,9 +213,9 @@ fn get_executor_option<'a>(
pub(crate) async fn matches(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
exp: &Expression,
l: Value,
r: Value,
@ -230,9 +230,9 @@ pub(crate) async fn matches(
pub(crate) async fn knn(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
exp: &Expression,
) -> Result<Value, Error> {
match get_executor_option(ctx, doc, exp) {

View file

@ -11,7 +11,7 @@ impl<R> Stream for ChannelStream<R> {
type Item = R;
fn poll_next(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
cx: &mut std::task::Context,
) -> std::task::Poll<Option<Self::Item>> {
self.0.recv().poll_unpin(cx).map(|x| x.ok())
}
@ -62,7 +62,7 @@ impl<R> Stream for ReadableStream<R> {
fn poll_next(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
cx: &mut std::task::Context,
) -> std::task::Poll<Option<Self::Item>> {
self.0.poll_next_unpin(cx)
}

View file

@ -22,9 +22,9 @@ use js::{Class, Ctx, Function, Module, Promise};
/// # Safety
/// Caller must ensure that the runtime from which `Ctx` originates cannot outlife 'a.
pub unsafe fn create_query_data<'a>(
context: &'a Context<'a>,
context: &'a Context,
opt: &'a Options,
doc: Option<&'a CursorDoc<'a>>,
doc: Option<&'a CursorDoc>,
ctx: &Ctx<'_>,
) -> Result<(), js::Error> {
// remove the restricting lifetime.
@ -47,9 +47,9 @@ pub unsafe fn create_query_data<'a>(
}
pub async fn run(
context: &Context<'_>,
context: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
src: &str,
arg: Vec<Value>,
) -> Result<Value, Error> {

View file

@ -15,6 +15,7 @@ use crate::{
#[allow(clippy::module_inception)]
mod classes;
use crate::ctx::MutableContext;
pub use classes::Query;
pub const QUERY_DATA_PROP_NAME: &str = "__query_context__";
@ -22,9 +23,9 @@ pub const QUERY_DATA_PROP_NAME: &str = "__query_context__";
/// A class to carry the data to run subqueries.
#[non_exhaustive]
pub struct QueryContext<'js> {
pub context: &'js Context<'js>,
pub context: &'js Context,
pub opt: &'js Options,
pub doc: Option<&'js CursorDoc<'js>>,
pub doc: Option<&'js CursorDoc>,
}
impl<'js> Trace<'js> for QueryContext<'js> {
@ -67,18 +68,19 @@ pub async fn query<'js>(
&**borrow_store.insert(borrow)
} else {
let Coerced(query_text) = Coerced::<String>::from_js(&ctx, query)?;
query_store.insert(classes::Query::new(ctx.clone(), query_text, variables)?)
query_store.insert(Query::new(ctx.clone(), query_text, variables)?)
};
let context = Context::new(this.context);
let context = query
let mut context = MutableContext::new(this.context);
query
.clone()
.vars
.attach(context)
.attach(&mut context)
.map_err(|e| Exception::throw_message(&ctx, &e.to_string()))?;
let context = context.freeze();
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)
Ok(value)
}

View file

@ -9,7 +9,7 @@ use crate::sql::Value;
use reblessive::tree::Stk;
pub async fn analyze(
(stk, ctx, opt): (&mut Stk, &Context<'_>, Option<&Options>),
(stk, ctx, opt): (&mut Stk, &Context, Option<&Options>),
(az, val): (Value, Value),
) -> Result<Value, Error> {
if let (Some(opt), Value::Strand(az), Value::Strand(val)) = (opt, az, val) {
@ -21,17 +21,17 @@ pub async fn analyze(
}
pub async fn score(
(ctx, doc): (&Context<'_>, Option<&CursorDoc<'_>>),
(ctx, doc): (&Context, Option<&CursorDoc>),
(match_ref,): (Value,),
) -> Result<Value, Error> {
if let Some((exe, doc, thg)) = get_execution_context(ctx, doc) {
return exe.score(ctx, &match_ref, thg, doc.ir).await;
return exe.score(ctx, &match_ref, thg, doc.ir.as_ref()).await;
}
Ok(Value::None)
}
pub async fn highlight(
(ctx, doc): (&Context<'_>, Option<&CursorDoc<'_>>),
(ctx, doc): (&Context, Option<&CursorDoc>),
args: (Value, Value, Value, Option<Value>),
) -> Result<Value, Error> {
if let Some((exe, doc, thg)) = get_execution_context(ctx, doc) {
@ -42,7 +42,7 @@ pub async fn highlight(
}
pub async fn offsets(
(ctx, doc): (&Context<'_>, Option<&CursorDoc<'_>>),
(ctx, doc): (&Context, Option<&CursorDoc>),
(match_ref, partial): (Value, Option<Value>),
) -> Result<Value, Error> {
if let Some((exe, _, thg)) = get_execution_context(ctx, doc) {

View file

@ -8,7 +8,7 @@ use crate::sql::value::Value;
use crate::sql::{Closure, Function};
pub async fn chain(
(stk, ctx, opt, doc): (&mut Stk, &Context<'_>, &Options, Option<&CursorDoc<'_>>),
(stk, ctx, opt, doc): (&mut Stk, &Context, &Options, Option<&CursorDoc>),
(value, worker): (Value, Closure),
) -> Result<Value, Error> {
let fnc = Function::Anonymous(worker.into(), vec![value]);

View file

@ -4,7 +4,7 @@ use crate::sql::Duration;
use crate::sql::Value;
/// Sleep during the provided duration parameter.
pub async fn sleep(ctx: &Context<'_>, (dur,): (Duration,)) -> Result<Value, Error> {
pub async fn sleep(ctx: &Context, (dur,): (Duration,)) -> Result<Value, Error> {
// Calculate the sleep duration
let dur = match (ctx.timeout(), dur.0) {
(Some(t), d) if t < d => t,

View file

@ -32,7 +32,7 @@ pub fn duration((val,): (Value,)) -> Result<Value, Error> {
}
pub async fn field(
(stk, ctx, opt, doc): (&mut Stk, &Context<'_>, Option<&Options>, Option<&CursorDoc<'_>>),
(stk, ctx, opt, doc): (&mut Stk, &Context, Option<&Options>, Option<&CursorDoc>),
(val,): (String,),
) -> Result<Value, Error> {
match opt {
@ -50,7 +50,7 @@ pub async fn field(
}
pub async fn fields(
(stk, ctx, opt, doc): (&mut Stk, &Context<'_>, Option<&Options>, Option<&CursorDoc<'_>>),
(stk, ctx, opt, doc): (&mut Stk, &Context, Option<&Options>, Option<&CursorDoc>),
(val,): (Vec<String>,),
) -> Result<Value, Error> {
match opt {

View file

@ -45,7 +45,7 @@ async fn decode_response(res: Response) -> Result<Value, Error> {
}
}
pub async fn head(ctx: &Context<'_>, uri: Strand, opts: impl Into<Object>) -> Result<Value, Error> {
pub async fn head(ctx: &Context, uri: Strand, opts: impl Into<Object>) -> Result<Value, Error> {
// Check if the URI is valid and allowed
let url = Url::parse(&uri).map_err(|_| Error::InvalidUrl(uri.to_string()))?;
ctx.check_allowed_net(&url)?;
@ -74,7 +74,7 @@ pub async fn head(ctx: &Context<'_>, uri: Strand, opts: impl Into<Object>) -> Re
}
}
pub async fn get(ctx: &Context<'_>, uri: Strand, opts: impl Into<Object>) -> Result<Value, Error> {
pub async fn get(ctx: &Context, uri: Strand, opts: impl Into<Object>) -> Result<Value, Error> {
// Check if the URI is valid and allowed
let url = Url::parse(&uri).map_err(|_| Error::InvalidUrl(uri.to_string()))?;
ctx.check_allowed_net(&url)?;
@ -101,7 +101,7 @@ pub async fn get(ctx: &Context<'_>, uri: Strand, opts: impl Into<Object>) -> Res
}
pub async fn put(
ctx: &Context<'_>,
ctx: &Context,
uri: Strand,
body: Value,
opts: impl Into<Object>,
@ -134,7 +134,7 @@ pub async fn put(
}
pub async fn post(
ctx: &Context<'_>,
ctx: &Context,
uri: Strand,
body: Value,
opts: impl Into<Object>,
@ -167,7 +167,7 @@ pub async fn post(
}
pub async fn patch(
ctx: &Context<'_>,
ctx: &Context,
uri: Strand,
body: Value,
opts: impl Into<Object>,
@ -199,11 +199,7 @@ pub async fn patch(
decode_response(res).await
}
pub async fn delete(
ctx: &Context<'_>,
uri: Strand,
opts: impl Into<Object>,
) -> Result<Value, Error> {
pub async fn delete(ctx: &Context, uri: Strand, opts: impl Into<Object>) -> Result<Value, Error> {
// Check if the URI is valid and allowed
let url = Url::parse(&uri).map_err(|_| Error::InvalidUrl(uri.to_string()))?;
ctx.check_allowed_net(&url)?;

View file

@ -73,11 +73,11 @@ pub mod distance {
}
pub fn knn(
(ctx, doc): (&Context<'_>, Option<&CursorDoc<'_>>),
(ctx, doc): (&Context, Option<&CursorDoc>),
(knn_ref,): (Option<Value>,),
) -> Result<Value, Error> {
if let Some((_exe, doc, thg)) = get_execution_context(ctx, doc) {
if let Some(ir) = doc.ir {
if let Some(ir) = &doc.ir {
if let Some(d) = ir.dist() {
return Ok(d.into());
}

View file

@ -59,7 +59,7 @@ impl Analyzer {
pub(super) async fn extract_querying_terms(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
t: &Terms,
content: String,
@ -97,7 +97,7 @@ impl Analyzer {
pub(in crate::idx) async fn extract_indexing_terms(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
t: &Terms,
content: Value,
@ -128,7 +128,7 @@ impl Analyzer {
pub(super) async fn extract_terms_with_frequencies(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
terms: &mut Terms,
field_content: Vec<Value>,
@ -170,7 +170,7 @@ impl Analyzer {
pub(super) async fn extract_terms_with_frequencies_with_offsets(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
terms: &mut Terms,
content: Vec<Value>,
@ -213,7 +213,7 @@ impl Analyzer {
async fn analyze_content(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
content: Vec<Value>,
stage: FilteringStage,
@ -229,7 +229,7 @@ impl Analyzer {
async fn analyze_value(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
val: Value,
stage: FilteringStage,
@ -261,7 +261,7 @@ impl Analyzer {
async fn generate_tokens(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
stage: FilteringStage,
mut input: String,
@ -291,7 +291,7 @@ impl Analyzer {
pub(crate) async fn analyze(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
input: String,
) -> Result<Value, Error> {
@ -302,7 +302,7 @@ impl Analyzer {
#[cfg(test)]
mod tests {
use super::Analyzer;
use crate::ctx::Context;
use crate::ctx::MutableContext;
use crate::dbs::Options;
use crate::idx::ft::analyzer::filter::FilteringStage;
use crate::idx::ft::analyzer::tokenizer::{Token, Tokens};
@ -316,7 +316,9 @@ mod tests {
async fn get_analyzer_tokens(def: &str, input: &str) -> Tokens {
let ds = Datastore::new("memory").await.unwrap();
let txn = ds.transaction(TransactionType::Read, LockType::Optimistic).await.unwrap();
let ctx = Context::default().with_transaction(Arc::new(txn));
let mut ctx = MutableContext::default();
ctx.set_transaction(Arc::new(txn));
let ctx = ctx.freeze();
let mut stmt = syn::parse(&format!("DEFINE {def}")).unwrap();
let Some(Statement::Define(DefineStatement::Analyzer(az))) = stmt.0 .0.pop() else {

View file

@ -98,7 +98,7 @@ impl VersionedSerdeState for State {}
impl FtIndex {
pub(crate) async fn new(
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
az: &str,
index_key_base: IndexKeyBase,
@ -188,7 +188,7 @@ impl FtIndex {
pub(crate) async fn remove_document(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
rid: &Thing,
) -> Result<(), Error> {
let tx = ctx.tx();
@ -241,7 +241,7 @@ impl FtIndex {
pub(crate) async fn index_document(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
rid: &Thing,
content: Vec<Value>,
@ -351,7 +351,7 @@ impl FtIndex {
pub(super) async fn extract_querying_terms(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
query_string: String,
) -> Result<(TermsList, TermsSet), Error> {
@ -470,7 +470,7 @@ impl FtIndex {
Ok(Value::None)
}
pub(crate) async fn statistics(&self, ctx: &Context<'_>) -> Result<FtStatistics, Error> {
pub(crate) async fn statistics(&self, ctx: &Context) -> Result<FtStatistics, Error> {
let txn = ctx.tx();
let res = FtStatistics {
doc_ids: self.doc_ids.read().await.statistics(&txn).await?,
@ -481,7 +481,7 @@ impl FtIndex {
Ok(res)
}
pub(crate) async fn finish(&self, ctx: &Context<'_>) -> Result<(), Error> {
pub(crate) async fn finish(&self, ctx: &Context) -> Result<(), Error> {
let txn = ctx.tx();
self.doc_ids.write().await.finish(&txn).await?;
self.doc_lengths.write().await.finish(&txn).await?;
@ -528,7 +528,7 @@ impl HitsIterator {
#[cfg(test)]
mod tests {
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
use crate::dbs::Options;
use crate::idx::ft::scorer::{BM25Scorer, Score};
use crate::idx::ft::{FtIndex, HitsIterator};
@ -544,7 +544,7 @@ mod tests {
use test_log::test;
async fn check_hits(
ctx: &Context<'_>,
ctx: &Context,
hits: Option<HitsIterator>,
scr: BM25Scorer,
e: Vec<(&Thing, Option<Score>)>,
@ -567,7 +567,7 @@ mod tests {
async fn search(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
fti: &FtIndex,
qs: &str,
@ -587,8 +587,8 @@ mod tests {
az: Arc<DefineAnalyzerStatement>,
order: u32,
hl: bool,
) -> (Context<'a>, Options, FtIndex) {
let mut ctx = Context::default();
) -> (Context, Options, FtIndex) {
let mut ctx = MutableContext::default();
let tx = ds.transaction(tt, Optimistic).await.unwrap();
let p = SearchParams {
az: az.name.clone(),
@ -615,10 +615,10 @@ mod tests {
.unwrap();
let txn = Arc::new(tx);
ctx.set_transaction(txn);
(ctx, Options::default(), fti)
(ctx.freeze(), Options::default(), fti)
}
pub(super) async fn finish(ctx: &Context<'_>, fti: FtIndex) {
pub(super) async fn finish(ctx: &Context, fti: FtIndex) {
fti.finish(ctx).await.unwrap();
let tx = ctx.tx();
tx.commit().await.unwrap();

View file

@ -9,7 +9,6 @@ use crate::idx::trees::knn::Ids64;
use crate::sql::{Cond, Thing, Value};
use ahash::HashMap;
use reblessive::tree::Stk;
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::collections::VecDeque;
use std::sync::Arc;
@ -31,11 +30,7 @@ impl<'a> Default for HnswConditionChecker<'a> {
}
impl<'a> HnswConditionChecker<'a> {
pub(in crate::idx) fn new_cond(
ctx: &'a Context<'_>,
opt: &'a Options,
cond: Arc<Cond>,
) -> Self {
pub(in crate::idx) fn new_cond(ctx: &'a Context, opt: &'a Options, cond: Arc<Cond>) -> Self {
Self::HnswCondition(HnswCondChecker {
ctx,
opt,
@ -81,7 +76,7 @@ impl<'a> HnswConditionChecker<'a> {
}
impl<'a> MTreeConditionChecker<'a> {
pub fn new_cond(ctx: &'a Context<'_>, opt: &'a Options, 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,
@ -94,7 +89,7 @@ impl<'a> MTreeConditionChecker<'a> {
}
}
pub fn new(ctx: &'a Context<'a>) -> Self {
pub fn new(ctx: &'a Context) -> Self {
Self::MTree(MTreeChecker {
ctx,
})
@ -131,7 +126,7 @@ impl<'a> MTreeConditionChecker<'a> {
}
pub struct MTreeChecker<'a> {
ctx: &'a Context<'a>,
ctx: &'a Context,
}
impl<'a> MTreeChecker<'a> {
@ -147,7 +142,8 @@ impl<'a> MTreeChecker<'a> {
let txn = self.ctx.tx();
for (doc_id, dist) in res {
if let Some(key) = doc_ids.get_doc_key(&txn, doc_id).await? {
result.push_back((key.into(), dist, None));
let rid: Thing = key.into();
result.push_back((rid.into(), dist, None));
}
}
Ok(result)
@ -155,7 +151,7 @@ impl<'a> MTreeChecker<'a> {
}
struct CheckerCacheEntry {
record: Option<(Thing, Value)>,
record: Option<(Arc<Thing>, Arc<Value>)>,
truthy: bool,
}
@ -179,23 +175,24 @@ impl CheckerCacheEntry {
async fn build(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
rid: Option<Thing>,
cond: &Cond,
) -> Result<Self, Error> {
if let Some(rid) = rid {
let rid = Arc::new(rid);
let txn = ctx.tx();
let val = Iterable::fetch_thing(&txn, opt, &rid).await?;
if !val.is_none_or_null() {
let (value, truthy) = {
let cursor_doc = CursorDoc {
rid: Some(&rid),
let mut cursor_doc = CursorDoc {
rid: Some(rid.clone()),
ir: None,
doc: Cow::Owned(val),
doc: val.into(),
};
let truthy = cond.compute(stk, ctx, opt, Some(&cursor_doc)).await?.is_truthy();
(cursor_doc.doc.into_owned(), truthy)
(cursor_doc.doc.as_arc(), truthy)
};
return Ok(CheckerCacheEntry {
record: Some((rid, value)),
@ -211,7 +208,7 @@ impl CheckerCacheEntry {
}
pub struct MTreeCondChecker<'a> {
ctx: &'a Context<'a>,
ctx: &'a Context,
opt: &'a Options,
cond: Arc<Cond>,
cache: HashMap<DocId, CheckerCacheEntry>,
@ -268,7 +265,7 @@ impl<'a> HnswChecker {
let mut result = VecDeque::with_capacity(res.len());
for (doc_id, dist) in res {
if let Some(rid) = docs.get_thing(doc_id) {
result.push_back((rid.clone(), dist, None));
result.push_back((rid.clone().into(), dist, None));
}
}
Ok(result)
@ -276,7 +273,7 @@ impl<'a> HnswChecker {
}
pub struct HnswCondChecker<'a> {
ctx: &'a Context<'a>,
ctx: &'a Context,
opt: &'a Options,
cond: Arc<Cond>,
cache: HashMap<DocId, CheckerCacheEntry>,

View file

@ -105,7 +105,7 @@ impl InnerQueryExecutor {
#[allow(clippy::mutable_key_type)]
pub(super) async fn new(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
table: &Table,
im: IndexesMap,
@ -276,10 +276,10 @@ impl QueryExecutor {
pub(crate) async fn knn(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
thg: &Thing,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
exp: &Expression,
) -> Result<Value, Error> {
if let Some(IterationStage::Iterate(e)) = ctx.get_iteration_stage() {
@ -535,7 +535,7 @@ impl QueryExecutor {
pub(crate) async fn matches(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
thg: &Thing,
exp: &Expression,
@ -559,7 +559,7 @@ impl QueryExecutor {
async fn matches_with_doc_id(
&self,
ctx: &Context<'_>,
ctx: &Context,
thg: &Thing,
ft: &FtEntry,
) -> Result<bool, Error> {
@ -592,7 +592,7 @@ impl QueryExecutor {
async fn matches_with_value(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
ft: &FtEntry,
l: Value,
@ -634,7 +634,7 @@ impl QueryExecutor {
pub(crate) async fn highlight(
&self,
ctx: &Context<'_>,
ctx: &Context,
thg: &Thing,
hlp: HighlightParams,
doc: &Value,
@ -651,7 +651,7 @@ impl QueryExecutor {
pub(crate) async fn offsets(
&self,
ctx: &Context<'_>,
ctx: &Context,
thg: &Thing,
match_ref: Value,
partial: bool,
@ -666,10 +666,10 @@ impl QueryExecutor {
pub(crate) async fn score(
&self,
ctx: &Context<'_>,
ctx: &Context,
match_ref: &Value,
rid: &Thing,
ir: Option<&IteratorRecord>,
ir: Option<&Arc<IteratorRecord>>,
) -> Result<Value, Error> {
if let Some(e) = self.get_ft_entry(match_ref) {
if let Some(scorer) = &e.0.scorer {
@ -714,7 +714,7 @@ struct Inner {
impl FtEntry {
async fn new(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
ft: &FtIndex,
io: IndexOption,
@ -749,7 +749,7 @@ pub(super) struct MtEntry {
impl MtEntry {
async fn new(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
mt: &MTreeIndex,
o: &[Number],
@ -777,7 +777,7 @@ impl HnswEntry {
#[allow(clippy::too_many_arguments)]
async fn new(
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
h: SharedHnswIndex,
v: &[Number],

View file

@ -12,6 +12,7 @@ use crate::sql::statements::DefineIndexStatement;
use crate::sql::{Array, Ident, Thing, Value};
use radix_trie::Trie;
use std::collections::VecDeque;
use std::sync::Arc;
pub(crate) type IteratorRef = u16;
@ -117,7 +118,7 @@ pub(crate) enum ThingIterator {
impl ThingIterator {
pub(crate) async fn next_batch<B: IteratorBatch>(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
txn: &Transaction,
size: u32,
) -> Result<B, Error> {
@ -136,7 +137,7 @@ impl ThingIterator {
}
}
pub(crate) type CollectorRecord = (Thing, IteratorRecord, Option<Value>);
pub(crate) type CollectorRecord = (Arc<Thing>, IteratorRecord, Option<Arc<Value>>);
pub(crate) struct IndexEqualThingIterator {
irf: IteratorRef,
@ -179,7 +180,7 @@ impl IndexEqualThingIterator {
*beg = key;
}
let mut records = B::with_capacity(res.len());
res.into_iter().for_each(|(_, val)| records.add((val.into(), irf.into(), None)));
res.into_iter().for_each(|(_, val)| records.add((Arc::new(val.into()), irf.into(), None)));
Ok(records)
}
@ -310,7 +311,7 @@ impl IndexRangeThingIterator {
let mut records = B::with_capacity(res.len());
res.into_iter()
.filter(|(k, _)| self.r.matches(k))
.for_each(|(_, v)| records.add((v.into(), self.irf.into(), None)));
.for_each(|(_, v)| records.add((Arc::new(v.into()), self.irf.into(), None)));
Ok(records)
}
}
@ -350,7 +351,7 @@ impl IndexUnionThingIterator {
async fn next_batch<B: IteratorBatch>(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
tx: &Transaction,
limit: u32,
) -> Result<B, Error> {
@ -404,7 +405,7 @@ impl JoinThingIterator {
impl JoinThingIterator {
async fn next_current_remote_batch(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
tx: &Transaction,
limit: u32,
) -> Result<bool, Error> {
@ -425,7 +426,7 @@ impl JoinThingIterator {
async fn next_current_local<F>(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
tx: &Transaction,
limit: u32,
new_iter: F,
@ -435,8 +436,8 @@ impl JoinThingIterator {
{
while !ctx.is_done() {
while let Some((thing, _, _)) = self.current_remote_batch.pop_front() {
let k: Key = (&thing).into();
let value = Value::from(thing);
let k: Key = thing.as_ref().into();
let value = Value::from(thing.as_ref().clone());
if self.distinct.insert(k, true).is_none() {
self.current_local =
Some(new_iter(&self.ns, &self.db, &self.ix_what, &self.ix_name, value));
@ -452,7 +453,7 @@ impl JoinThingIterator {
async fn next_batch<F, B: IteratorBatch>(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
tx: &Transaction,
limit: u32,
new_iter: F,
@ -489,7 +490,7 @@ impl IndexJoinThingIterator {
async fn next_batch<B: IteratorBatch>(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
tx: &Transaction,
limit: u32,
) -> Result<B, Error> {
@ -526,7 +527,8 @@ impl UniqueEqualThingIterator {
async fn next_batch<B: IteratorBatch>(&mut self, tx: &Transaction) -> Result<B, Error> {
if let Some(key) = self.key.take() {
if let Some(val) = tx.get(key, None).await? {
let record = (val.into(), self.irf.into(), None);
let rid: Thing = val.into();
let record = (rid.into(), self.irf.into(), None);
return Ok(B::from_one(record));
}
}
@ -609,13 +611,15 @@ impl UniqueRangeThingIterator {
return Ok(records);
}
if self.r.matches(&k) {
records.add((v.into(), self.irf.into(), None));
let rid: Thing = v.into();
records.add((rid.into(), self.irf.into(), None));
}
}
let end = self.r.end.clone();
if self.r.matches(&end) {
if let Some(v) = tx.get(end, None).await? {
records.add((v.into(), self.irf.into(), None));
let rid: Thing = v.into();
records.add((rid.into(), self.irf.into(), None));
}
}
self.done = true;
@ -652,7 +656,7 @@ impl UniqueUnionThingIterator {
async fn next_batch<B: IteratorBatch>(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
tx: &Transaction,
limit: u32,
) -> Result<B, Error> {
@ -663,7 +667,8 @@ impl UniqueUnionThingIterator {
break;
}
if let Some(val) = tx.get(key, None).await? {
results.add((val.into(), self.irf.into(), None));
let rid: Thing = val.into();
results.add((rid.into(), self.irf.into(), None));
if results.len() >= limit {
break;
}
@ -687,7 +692,7 @@ impl UniqueJoinThingIterator {
async fn next_batch<B: IteratorBatch>(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
tx: &Transaction,
limit: u32,
) -> Result<B, Error> {
@ -726,7 +731,7 @@ impl MatchesThingIterator {
async fn next_batch<B: IteratorBatch>(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
tx: &Transaction,
limit: u32,
) -> Result<B, Error> {
@ -740,7 +745,7 @@ impl MatchesThingIterator {
doc_id: Some(doc_id),
dist: None,
};
records.add((thg, ir, None));
records.add((thg.into(), ir, None));
self.hits_left -= 1;
} else {
break;
@ -753,7 +758,7 @@ impl MatchesThingIterator {
}
}
pub(crate) type KnnIteratorResult = (Thing, f64, Option<Value>);
pub(crate) type KnnIteratorResult = (Arc<Thing>, f64, Option<Arc<Value>>);
pub(crate) struct KnnIterator {
irf: IteratorRef,
@ -769,7 +774,7 @@ impl KnnIterator {
}
async fn next_batch<B: IteratorBatch>(
&mut self,
ctx: &Context<'_>,
ctx: &Context,
limit: u32,
) -> Result<B, Error> {
let limit = limit as usize;

View file

@ -19,11 +19,12 @@ use crate::sql::{Cond, Table};
use reblessive::tree::Stk;
use std::collections::HashMap;
use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc;
pub(crate) struct QueryPlanner<'a> {
opt: &'a Options,
with: &'a Option<With>,
cond: &'a Option<Cond>,
pub(crate) struct QueryPlanner {
opt: Arc<Options>,
with: Option<Arc<With>>,
cond: Option<Arc<Cond>>,
/// There is one executor per table
executors: HashMap<String, QueryExecutor>,
requires_distinct: bool,
@ -32,8 +33,8 @@ pub(crate) struct QueryPlanner<'a> {
iteration_index: AtomicU8,
}
impl<'a> QueryPlanner<'a> {
pub(crate) fn new(opt: &'a Options, with: &'a Option<With>, cond: &'a Option<Cond>) -> Self {
impl QueryPlanner {
pub(crate) fn new(opt: Arc<Options>, with: Option<Arc<With>>, cond: Option<Arc<Cond>>) -> Self {
Self {
opt,
with,
@ -49,19 +50,28 @@ impl<'a> QueryPlanner<'a> {
pub(crate) async fn add_iterables(
&mut self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
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, &t, self.cond, self.with).await? {
match Tree::build(
stk,
ctx,
&self.opt,
&t,
self.cond.as_ref().map(|w| w.as_ref()),
self.with.as_ref().map(|c| c.as_ref()),
)
.await?
{
Some(tree) => {
is_knn = is_knn || !tree.knn_expressions.is_empty();
let mut exe = InnerQueryExecutor::new(
stk,
ctx,
self.opt,
&self.opt,
&t,
tree.index_map,
tree.knn_expressions,
@ -69,7 +79,11 @@ impl<'a> QueryPlanner<'a> {
tree.knn_condition,
)
.await?;
match PlanBuilder::build(tree.root, self.with, tree.with_indexes)? {
match PlanBuilder::build(
tree.root,
self.with.as_ref().map(|w| w.as_ref()),
tree.with_indexes,
)? {
Plan::SingleIndex(exp, io) => {
if io.require_distinct() {
self.requires_distinct = true;

View file

@ -31,7 +31,7 @@ pub(super) struct PlanBuilder {
impl PlanBuilder {
pub(super) fn build(
root: Node,
with: &Option<With>,
with: Option<&With>,
with_indexes: Vec<IndexRef>,
) -> Result<Plan, Error> {
if let Some(With::NoIndex) = with {

View file

@ -30,11 +30,11 @@ impl Tree {
/// that can be resolved by an index.
pub(super) async fn build<'a>(
stk: &mut Stk,
ctx: &'a Context<'_>,
ctx: &'a Context,
opt: &'a Options,
table: &'a Table,
cond: &'a Option<Cond>,
with: &'a Option<With>,
cond: Option<&Cond>,
with: Option<&With>,
) -> Result<Option<Self>, Error> {
let mut b = TreeBuilder::new(ctx, opt, table, with);
if let Some(cond) = cond {
@ -59,10 +59,10 @@ impl Tree {
}
struct TreeBuilder<'a> {
ctx: &'a Context<'a>,
ctx: &'a Context,
opt: &'a Options,
table: &'a Table,
with: &'a Option<With>,
with: Option<&'a With>,
schemas: HashMap<Table, SchemaCache>,
idioms_indexes: HashMap<Table, HashMap<Idiom, LocalIndexRefs>>,
resolved_expressions: HashMap<Arc<Expression>, ResolvedExpression>,
@ -85,12 +85,7 @@ pub(super) type LocalIndexRefs = Vec<IndexRef>;
pub(super) type RemoteIndexRefs = Arc<Vec<(Idiom, LocalIndexRefs)>>;
impl<'a> TreeBuilder<'a> {
fn new(
ctx: &'a Context<'_>,
opt: &'a Options,
table: &'a Table,
with: &'a Option<With>,
) -> Self {
fn new(ctx: &'a Context, opt: &'a Options, table: &'a Table, with: Option<&'a With>) -> Self {
let with_indexes = match with {
Some(With::Index(ixs)) => Vec::with_capacity(ixs.len()),
_ => vec![],
@ -225,7 +220,7 @@ impl<'a> TreeBuilder<'a> {
for ix in schema.indexes.iter() {
if ix.cols.len() == 1 && ix.cols[0].eq(i) {
let ixr = self.index_map.definitions.len() as IndexRef;
if let Some(With::Index(ixs)) = self.with {
if let Some(With::Index(ixs)) = &self.with {
if ixs.contains(&ix.name.0) {
self.with_indexes.push(ixr);
}

View file

@ -39,7 +39,7 @@ pub struct MTreeIndex {
}
struct MTreeSearchContext<'a> {
ctx: &'a Context<'a>,
ctx: &'a Context,
pt: SharedVector,
k: usize,
store: &'a MTreeStore,
@ -135,7 +135,7 @@ impl MTreeIndex {
pub async fn knn_search(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
v: &[Number],
k: usize,
mut chk: MTreeConditionChecker<'_>,
@ -1473,7 +1473,7 @@ impl VersionedSerdeState for MState {}
#[cfg(test)]
mod tests {
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
use crate::err::Error;
use crate::idx::docids::{DocId, DocIds};
use crate::idx::planner::checker::MTreeConditionChecker;
@ -1491,19 +1491,20 @@ mod tests {
use std::collections::VecDeque;
use test_log::test;
async fn new_operation<'a>(
async fn new_operation(
ds: &Datastore,
t: &MTree,
tt: TransactionType,
cache_size: usize,
) -> (Context<'a>, TreeStore<MTreeNode>) {
) -> (Context, TreeStore<MTreeNode>) {
let st = ds
.index_store()
.get_store_mtree(TreeNodeProvider::Debug, t.state.generation, tt, cache_size)
.await;
let tx = ds.transaction(tt, Optimistic).await.unwrap().enclose();
let ctx = Context::default().with_transaction(tx);
(ctx, st)
let mut ctx = MutableContext::default();
ctx.set_transaction(tx);
(ctx.freeze(), st)
}
async fn finish_operation(

View file

@ -69,7 +69,7 @@ where
pub(in crate::idx) async fn get_node_txn(
&self,
ctx: &Context<'_>,
ctx: &Context,
node_id: NodeId,
) -> Result<Arc<StoredNode<N>>, Error> {
match self {

View file

@ -1,7 +1,7 @@
use super::tr::Transactor;
use super::tx::Transaction;
use crate::cf;
use crate::ctx::Context;
use crate::ctx::MutableContext;
#[cfg(feature = "jwks")]
use crate::dbs::capabilities::NetTarget;
use crate::dbs::{
@ -414,7 +414,9 @@ impl Datastore {
// Create and new root user definition
let stm = DefineUserStatement::from((Base::Root, user, pass, INITIAL_USER_ROLE));
let opt = Options::new().with_auth(Arc::new(Auth::for_root(Role::Owner)));
let ctx = Context::default().with_transaction(txn.clone());
let mut ctx = MutableContext::default();
ctx.set_transaction(txn.clone());
let ctx = ctx.freeze();
catch!(txn, stm.compute(&ctx, &opt, None));
// We added a user, so commit the transaction
txn.commit().await
@ -684,7 +686,7 @@ impl Datastore {
// Create a new query executor
let mut exe = Executor::new(self);
// Create a default context
let mut ctx = Context::from_ds(
let mut ctx = MutableContext::from_ds(
self.query_timeout,
self.capabilities.clone(),
self.index_stores.clone(),
@ -702,11 +704,11 @@ impl Datastore {
ctx.add_notifications(Some(&channel.0));
}
// Start an execution context
let ctx = sess.context(ctx);
sess.context(&mut ctx);
// Store the query variables
let ctx = vars.attach(ctx)?;
vars.attach(&mut ctx)?;
// Process all statements
exe.execute(ctx, opt, ast).await
exe.execute(ctx.freeze(), opt, ast).await
}
/// Ensure a SQL [`Value`] is fully computed
@ -760,7 +762,7 @@ impl Datastore {
.with_strict(self.strict)
.with_auth_enabled(self.auth_enabled);
// Create a default context
let mut ctx = Context::default();
let mut ctx = MutableContext::default();
// Set context capabilities
ctx.add_capabilities(self.capabilities.clone());
// Set the global query timeout
@ -772,13 +774,15 @@ impl Datastore {
ctx.add_notifications(Some(&channel.0));
}
// Start an execution context
let ctx = sess.context(ctx);
sess.context(&mut ctx);
// Store the query variables
let ctx = vars.attach(ctx)?;
vars.attach(&mut ctx)?;
// Start a new transaction
let txn = self.transaction(val.writeable().into(), Optimistic).await?.enclose();
// Store the transaction
let ctx = ctx.with_transaction(txn.clone());
ctx.set_transaction(txn.clone());
// Freeze the context
let ctx = ctx.freeze();
// Compute the value
let res = stack.enter(|stk| val.compute(stk, &ctx, &opt, None)).finish().await;
// Store any data
@ -837,7 +841,7 @@ impl Datastore {
.with_strict(self.strict)
.with_auth_enabled(self.auth_enabled);
// Create a default context
let mut ctx = Context::default();
let mut ctx = MutableContext::default();
// Set context capabilities
ctx.add_capabilities(self.capabilities.clone());
// Set the global query timeout
@ -849,13 +853,15 @@ impl Datastore {
ctx.add_notifications(Some(&channel.0));
}
// Start an execution context
let ctx = sess.context(ctx);
sess.context(&mut ctx);
// Store the query variables
let ctx = vars.attach(ctx)?;
vars.attach(&mut ctx)?;
// Start a new transaction
let txn = self.transaction(val.writeable().into(), Optimistic).await?.enclose();
// Store the transaction
let ctx = ctx.with_transaction(txn.clone());
ctx.set_transaction(txn.clone());
// Free the context
let ctx = ctx.freeze();
// Compute the value
let res = stack.enter(|stk| val.compute(stk, &ctx, &opt, None)).finish().await;
// Store any data
@ -984,13 +990,15 @@ mod test {
.with_futures(true);
// Create a default context
let mut ctx = Context::default();
let mut ctx = MutableContext::default();
// Set context capabilities
ctx.add_capabilities(dbs.capabilities.clone());
// Start a new transaction
let txn = dbs.transaction(val.writeable().into(), Optimistic).await?;
// Store the transaction
let ctx = ctx.with_transaction(txn.enclose());
ctx.set_transaction(txn.enclose());
// Freeze the context
let ctx = ctx.freeze();
// Compute the value
let mut stack = reblessive::tree::TreeStack::new();
let res = stack.enter(|stk| val.compute(stk, &ctx, &opt, None)).finish().await.unwrap();

View file

@ -53,7 +53,7 @@ impl<'a> Stream for Scanner<'a> {
type Item = Result<(Key, Val), Error>;
fn poll_next(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
cx: &mut Context,
) -> Poll<Option<Result<(Key, Val), Error>>> {
// If we have results, return the first one
if let Some(v) = self.results.pop_front() {

View file

@ -3,6 +3,7 @@ use super::Key;
use super::Val;
use crate::cf;
use crate::dbs::node::Timestamp;
use crate::doc::CursorValue;
use crate::err::Error;
use crate::idg::u32::U32;
use crate::key::debug::Sprintable;
@ -11,10 +12,8 @@ use crate::kvs::clock::SizedClock;
use crate::kvs::stash::Stash;
use crate::sql;
use crate::sql::thing::Thing;
use crate::sql::Value;
use crate::vs::Versionstamp;
use sql::statements::DefineTableStatement;
use std::borrow::Cow;
use std::fmt;
use std::fmt::Debug;
use std::ops::Range;
@ -415,8 +414,8 @@ impl Transactor {
db: &str,
tb: &str,
id: &Thing,
previous: Cow<'_, Value>,
current: Cow<'_, Value>,
previous: CursorValue,
current: CursorValue,
store_difference: bool,
) {
self.cf.record_cf_change(ns, db, tb, id.clone(), previous, current, store_difference)

View file

@ -188,7 +188,7 @@ macro_rules! async_defer{
{
type Output = ::std::thread::Result<R>;
fn poll(self: ::std::pin::Pin<&mut Self>, cx: &mut ::std::task::Context<'_>) -> ::std::task::Poll<Self::Output>{
fn poll(self: ::std::pin::Pin<&mut Self>, cx: &mut ::std::task::Context) -> ::std::task::Poll<Self::Output>{
let pin = unsafe{ self.map_unchecked_mut(|x| &mut x.0) };
match ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(||{
pin.poll(cx)

View file

@ -135,9 +135,9 @@ impl Array {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
let mut x = Self::with_capacity(self.len());
for v in self.iter() {

View file

@ -1,4 +1,4 @@
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
@ -50,18 +50,20 @@ impl Block {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Duplicate context
let mut ctx = Context::new(ctx);
let mut ctx = MutableContext::new(ctx).freeze();
// Loop over the statements
for (i, v) in self.iter().enumerate() {
match v {
Entry::Set(v) => {
let val = v.compute(stk, &ctx, opt, doc).await?;
ctx.add_value(v.name.to_owned(), val);
let mut c = MutableContext::unfreeze(ctx)?;
c.add_value(v.name.to_owned(), val.into());
ctx = c.freeze();
}
Entry::Throw(v) => {
// Always errors immediately

View file

@ -37,9 +37,9 @@ impl Cast {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Compute the value to be cast and convert it
stk.run(|stk| self.1.compute(stk, ctx, opt, doc)).await?.convert_to(&self.0)

View file

@ -1,11 +1,11 @@
use super::{Ident, Kind};
use crate::ctx::MutableContext;
use crate::{ctx::Context, dbs::Options, doc::CursorDoc, err::Error, sql::value::Value};
use reblessive::tree::Stk;
use revision::revisioned;
use serde::{Deserialize, Serialize};
use std::fmt;
use super::{Ident, Kind};
pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Closure";
#[revisioned(revision = 1)]
@ -23,12 +23,12 @@ impl Closure {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
args: Vec<Value>,
) -> Result<Value, Error> {
let mut ctx = Context::new_isolated(ctx);
let mut ctx = MutableContext::new_isolated(ctx);
for (i, (name, kind)) in self.args.iter().enumerate() {
match (kind, args.get(i)) {
(Kind::Option(_), None) => continue,
@ -40,7 +40,7 @@ impl Closure {
}
(kind, Some(val)) => {
if let Ok(val) = val.to_owned().coerce_to(kind) {
ctx.add_value(name.to_string(), val);
ctx.add_value(name.to_string(), val.into());
} else {
return Err(Error::InvalidArguments {
name: "ANONYMOUS".to_string(),
@ -54,6 +54,7 @@ impl Closure {
}
}
let ctx = ctx.freeze();
let result = self.body.compute(stk, &ctx, opt, doc).await?;
if let Some(returns) = &self.returns {
result.coerce_to(returns).map_err(|e| e.function_check_from_coerce("ANONYMOUS"))

View file

@ -38,7 +38,7 @@ impl Data {
pub(crate) async fn rid(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
) -> Result<Option<Value>, Error> {
match self {

View file

@ -100,9 +100,9 @@ impl Expression {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
let (l, o, r) = match self {
Self::Unary {

View file

@ -66,7 +66,7 @@ impl Fetch {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
idioms: &mut Vec<Idiom>,
) -> Result<(), Error> {

View file

@ -78,15 +78,15 @@ impl Fields {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
group: bool,
) -> Result<Value, Error> {
if let Some(doc) = doc {
self.compute_value(stk, ctx, opt, doc, group).await
} else {
let doc = (&Value::None).into();
let doc = Value::None.into();
self.compute_value(stk, ctx, opt, &doc, group).await
}
}
@ -94,16 +94,16 @@ impl Fields {
async fn compute_value(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: &CursorDoc<'_>,
doc: &CursorDoc,
group: bool,
) -> Result<Value, Error> {
// Ensure futures are run
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, Some(doc)).await?,
true => doc.doc.as_ref().compute(stk, ctx, opt, Some(doc)).await?,
false => Value::base(),
};
for v in self.other() {

View file

@ -1,4 +1,4 @@
use crate::ctx::Context;
use crate::ctx::{Context, MutableContext};
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
@ -189,9 +189,9 @@ impl Function {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Ensure futures are run
let opt = &opt.new_with_futures(true);
@ -297,11 +297,12 @@ impl Function {
})
.await?;
// Duplicate context
let mut ctx = Context::new_isolated(ctx);
let mut ctx = MutableContext::new_isolated(ctx);
// Process the function arguments
for (val, (name, kind)) in a.into_iter().zip(&val.args) {
ctx.add_value(name.to_raw(), val.coerce_to(kind)?);
ctx.add_value(name.to_raw(), val.coerce_to(kind)?.into());
}
let ctx = ctx.freeze();
// Run the custom function
let result = match stk.run(|stk| val.block.compute(stk, &ctx, opt, doc)).await {
Err(Error::Return {

View file

@ -29,9 +29,9 @@ impl Future {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Process the future if enabled
match opt.futures {

View file

@ -184,9 +184,9 @@ impl Id {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Id, Error> {
match self {
Id::Number(v) => Ok(Id::Number(*v)),

View file

@ -164,9 +164,9 @@ impl Idiom {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
match self.first() {
// The starting part is a value
@ -182,7 +182,12 @@ impl Idiom {
_ => match doc {
// There is a current document
Some(v) => {
v.doc.get(stk, ctx, opt, doc, self).await?.compute(stk, ctx, opt, doc).await
v.doc
.as_ref()
.get(stk, ctx, opt, doc, self)
.await?
.compute(stk, ctx, opt, doc)
.await
}
// There isn't any document
None => {

View file

@ -19,9 +19,9 @@ impl Limit {
pub(crate) async fn process(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<usize, Error> {
match self.0.compute(stk, ctx, opt, doc).await {
// This is a valid limiting number

View file

@ -58,9 +58,9 @@ impl Model {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Ensure futures are run
let opt = &opt.new_with_futures(true);
@ -217,9 +217,9 @@ impl Model {
pub(crate) async fn compute(
&self,
_stk: &mut Stk,
_ctx: &Context<'_>,
_ctx: &Context,
_opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
Err(Error::InvalidModel {
message: String::from("Machine learning computation is not enabled."),

View file

@ -218,9 +218,9 @@ impl Object {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
let mut x = BTreeMap::new();
for (k, v) in self.iter() {

View file

@ -50,16 +50,16 @@ impl Param {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Find the variable by name
match self.as_str() {
// This is a special param
"this" | "self" => match doc {
// The base document exists
Some(v) => v.doc.compute(stk, ctx, opt, doc).await,
Some(v) => v.doc.as_ref().compute(stk, ctx, opt, doc).await,
// The base document does not exist
None => Ok(Value::None),
},

View file

@ -160,9 +160,9 @@ impl Range {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
Ok(Value::Range(Box::new(Range {
tb: self.tb.clone(),

View file

@ -19,9 +19,9 @@ impl Start {
pub(crate) async fn process(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<usize, Error> {
match self.0.compute(stk, ctx, opt, doc).await {
// This is a valid starting number

View file

@ -152,9 +152,9 @@ impl Statement {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
match self {
Self::Access(v) => v.compute(ctx, opt, doc).await,

View file

@ -232,9 +232,9 @@ fn random_string(length: usize) -> String {
async fn compute_grant(
stmt: &AccessStatementGrant,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
let base = match &stmt.base {
Some(base) => base.clone(),
@ -431,9 +431,9 @@ async fn compute_grant(
async fn compute_list(
stmt: &AccessStatementList,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
let base = match &stmt.base {
Some(base) => base.clone(),
@ -495,9 +495,9 @@ async fn compute_list(
async fn compute_revoke(
stmt: &AccessStatementRevoke,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
let base = match &stmt.base {
Some(base) => base.clone(),
@ -580,9 +580,9 @@ impl AccessStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
match self {
AccessStatement::Grant(stmt) => compute_grant(stmt, ctx, opt, _doc).await,

View file

@ -30,9 +30,9 @@ impl AlterStatement {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
match self {
Self::Table(ref v) => v.compute(stk, ctx, opt, doc).await,

View file

@ -32,9 +32,9 @@ impl AlterTableStatement {
pub(crate) async fn compute(
&self,
_stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Table, &Base::Db)?;

View file

@ -29,9 +29,9 @@ impl AnalyzeStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
match self {
AnalyzeStatement::Idx(tb, idx) => {

View file

@ -22,9 +22,9 @@ impl BreakStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
_ctx: &Context,
_opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
Err(Error::Break)
}

View file

@ -22,9 +22,9 @@ impl ContinueStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
_ctx: &Context,
_opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
Err(Error::Continue)
}

View file

@ -38,9 +38,9 @@ impl CreateStatement {
pub(crate) async fn compute(
&self,
stk: &mut Stk,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
doc: Option<&CursorDoc<'_>>,
doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Valid options?
opt.valid_for_db()?;

View file

@ -61,9 +61,9 @@ impl DefineAccessStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Actor, &self.base)?;

View file

@ -30,9 +30,9 @@ pub struct DefineAnalyzerStatement {
impl DefineAnalyzerStatement {
pub(crate) async fn compute(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Analyzer, &Base::Db)?;

View file

@ -29,9 +29,9 @@ impl DefineDatabaseStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Database, &Base::Ns)?;

View file

@ -30,9 +30,9 @@ impl DefineEventStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Event, &Base::Db)?;

View file

@ -40,9 +40,9 @@ impl DefineFieldStatement {
/// Process this type returning a computed simple Value
pub(crate) async fn compute(
&self,
ctx: &Context<'_>,
ctx: &Context,
opt: &Options,
_doc: Option<&CursorDoc<'_>>,
_doc: Option<&CursorDoc>,
) -> Result<Value, Error> {
// Allowed to run?
opt.is_allowed(Action::Edit, ResourceKind::Field, &Base::Db)?;

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