Remove Context lifetimes (#4484)
This commit is contained in:
parent
d7b392cf8b
commit
6e9d04d4d7
149 changed files with 971 additions and 801 deletions
core/src
cf
ctx
dbs
doc
allow.rsalter.rschangefeeds.rscheck.rsclean.rscompute.rscreate.rsdelete.rsdocument.rsedges.rsempty.rserase.rsevent.rsfield.rsindex.rsinsert.rslives.rsmerge.rspluck.rsprocess.rspurge.rsrelate.rsrelation.rsreset.rsselect.rsstore.rstable.rsupdate.rsupsert.rs
exe
fnc
idx
ft
planner
trees
kvs
mac
sql
|
@ -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();
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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?;
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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?;
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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())? {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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."),
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()?;
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue