Improve datastore configuration options (#2227)
This commit is contained in:
parent
67687496c6
commit
4b690c763b
79 changed files with 878 additions and 785 deletions
lib
benches
fuzz/fuzz_targets
src
api/engine/local
ctx
dbs
doc
err
fnc
iam
key
kvs
sql
tests
src
|
@ -13,14 +13,14 @@ macro_rules! query {
|
|||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let setup = $setup;
|
||||
if !setup.is_empty() {
|
||||
dbs.execute(setup, &ses, None, false).await.unwrap();
|
||||
dbs.execute(setup, &ses, None).await.unwrap();
|
||||
}
|
||||
(dbs, ses)
|
||||
});
|
||||
|
||||
b.iter(|| {
|
||||
futures::executor::block_on(async {
|
||||
black_box(dbs.execute(black_box($query), &ses, None, false).await).unwrap();
|
||||
black_box(dbs.execute(black_box($query), &ses, None).await).unwrap();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ fuzz_target!(|commands: &str| {
|
|||
return;
|
||||
}
|
||||
}
|
||||
let _ignore_the_result = dbs.execute(command, &ses, None, false).await;
|
||||
let _ignore_the_result = dbs.execute(command, &ses, None).await;
|
||||
|
||||
// TODO: Add some async timeout and `tokio::select!` between it and the query
|
||||
// Alternatively, wrap future in `tokio::time::Timeout`.
|
||||
|
|
|
@ -401,7 +401,6 @@ async fn router(
|
|||
(_, method, param): (i64, Method, Param),
|
||||
kvs: &Datastore,
|
||||
configured_root: &Option<Root<'_>>,
|
||||
strict: bool,
|
||||
session: &mut Session,
|
||||
vars: &mut BTreeMap<String, Value>,
|
||||
) -> Result<DbResponse> {
|
||||
|
@ -429,7 +428,7 @@ async fn router(
|
|||
[Value::Object(credentials)] => mem::take(credentials),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let response = crate::iam::signup::signup(kvs, strict, session, credentials).await?;
|
||||
let response = crate::iam::signup::signup(kvs, session, credentials).await?;
|
||||
Ok(DbResponse::Other(response.into()))
|
||||
}
|
||||
Method::Signin => {
|
||||
|
@ -438,8 +437,7 @@ async fn router(
|
|||
_ => unreachable!(),
|
||||
};
|
||||
let response =
|
||||
crate::iam::signin::signin(kvs, configured_root, strict, session, credentials)
|
||||
.await?;
|
||||
crate::iam::signin::signin(kvs, configured_root, session, credentials).await?;
|
||||
Ok(DbResponse::Other(response.into()))
|
||||
}
|
||||
Method::Authenticate => {
|
||||
|
@ -457,42 +455,42 @@ async fn router(
|
|||
Method::Create => {
|
||||
let statement = create_statement(&mut params);
|
||||
let query = Query(Statements(vec![Statement::Create(statement)]));
|
||||
let response = kvs.process(query, &*session, Some(vars.clone()), strict).await?;
|
||||
let response = kvs.process(query, &*session, Some(vars.clone())).await?;
|
||||
let value = take(true, response).await?;
|
||||
Ok(DbResponse::Other(value))
|
||||
}
|
||||
Method::Update => {
|
||||
let (one, statement) = update_statement(&mut params);
|
||||
let query = Query(Statements(vec![Statement::Update(statement)]));
|
||||
let response = kvs.process(query, &*session, Some(vars.clone()), strict).await?;
|
||||
let response = kvs.process(query, &*session, Some(vars.clone())).await?;
|
||||
let value = take(one, response).await?;
|
||||
Ok(DbResponse::Other(value))
|
||||
}
|
||||
Method::Patch => {
|
||||
let (one, statement) = patch_statement(&mut params);
|
||||
let query = Query(Statements(vec![Statement::Update(statement)]));
|
||||
let response = kvs.process(query, &*session, Some(vars.clone()), strict).await?;
|
||||
let response = kvs.process(query, &*session, Some(vars.clone())).await?;
|
||||
let value = take(one, response).await?;
|
||||
Ok(DbResponse::Other(value))
|
||||
}
|
||||
Method::Merge => {
|
||||
let (one, statement) = merge_statement(&mut params);
|
||||
let query = Query(Statements(vec![Statement::Update(statement)]));
|
||||
let response = kvs.process(query, &*session, Some(vars.clone()), strict).await?;
|
||||
let response = kvs.process(query, &*session, Some(vars.clone())).await?;
|
||||
let value = take(one, response).await?;
|
||||
Ok(DbResponse::Other(value))
|
||||
}
|
||||
Method::Select => {
|
||||
let (one, statement) = select_statement(&mut params);
|
||||
let query = Query(Statements(vec![Statement::Select(statement)]));
|
||||
let response = kvs.process(query, &*session, Some(vars.clone()), strict).await?;
|
||||
let response = kvs.process(query, &*session, Some(vars.clone())).await?;
|
||||
let value = take(one, response).await?;
|
||||
Ok(DbResponse::Other(value))
|
||||
}
|
||||
Method::Delete => {
|
||||
let (one, statement) = delete_statement(&mut params);
|
||||
let query = Query(Statements(vec![Statement::Delete(statement)]));
|
||||
let response = kvs.process(query, &*session, Some(vars.clone()), strict).await?;
|
||||
let response = kvs.process(query, &*session, Some(vars.clone())).await?;
|
||||
let value = take(one, response).await?;
|
||||
Ok(DbResponse::Other(value))
|
||||
}
|
||||
|
@ -501,7 +499,7 @@ async fn router(
|
|||
Some((query, mut bindings)) => {
|
||||
let mut vars = vars.clone();
|
||||
vars.append(&mut bindings);
|
||||
kvs.process(query, &*session, Some(vars), strict).await?
|
||||
kvs.process(query, &*session, Some(vars)).await?
|
||||
}
|
||||
None => unreachable!(),
|
||||
};
|
||||
|
@ -611,7 +609,7 @@ async fn router(
|
|||
}
|
||||
.into());
|
||||
}
|
||||
let responses = kvs.execute(&statements, &*session, Some(vars.clone()), strict).await?;
|
||||
let responses = kvs.execute(&statements, &*session, Some(vars.clone())).await?;
|
||||
for response in responses {
|
||||
response.result?;
|
||||
}
|
||||
|
@ -641,7 +639,7 @@ async fn router(
|
|||
let mut vars = BTreeMap::new();
|
||||
vars.insert("table".to_owned(), table);
|
||||
let response = kvs
|
||||
.execute("LIVE SELECT * FROM type::table($table)", &*session, Some(vars), strict)
|
||||
.execute("LIVE SELECT * FROM type::table($table)", &*session, Some(vars))
|
||||
.await?;
|
||||
let value = take(true, response).await?;
|
||||
Ok(DbResponse::Other(value))
|
||||
|
@ -653,8 +651,7 @@ async fn router(
|
|||
};
|
||||
let mut vars = BTreeMap::new();
|
||||
vars.insert("id".to_owned(), id);
|
||||
let response =
|
||||
kvs.execute("KILL type::string($id)", &*session, Some(vars), strict).await?;
|
||||
let response = kvs.execute("KILL type::string($id)", &*session, Some(vars)).await?;
|
||||
let value = take(true, response).await?;
|
||||
Ok(DbResponse::Other(value))
|
||||
}
|
||||
|
|
|
@ -116,6 +116,8 @@ pub(crate) fn router(
|
|||
}
|
||||
};
|
||||
|
||||
let kvs = kvs.with_strict_mode(address.strict);
|
||||
|
||||
let mut vars = BTreeMap::new();
|
||||
let mut stream = route_rx.into_stream();
|
||||
let configured_root = match address.auth {
|
||||
|
@ -134,15 +136,8 @@ pub(crate) fn router(
|
|||
};
|
||||
|
||||
while let Some(Some(route)) = stream.next().await {
|
||||
match super::router(
|
||||
route.request,
|
||||
&kvs,
|
||||
&configured_root,
|
||||
address.strict,
|
||||
&mut session,
|
||||
&mut vars,
|
||||
)
|
||||
.await
|
||||
match super::router(route.request, &kvs, &configured_root, &mut session, &mut vars)
|
||||
.await
|
||||
{
|
||||
Ok(value) => {
|
||||
let _ = route.response.into_send_async(Ok(value)).await;
|
||||
|
|
|
@ -102,6 +102,8 @@ pub(crate) fn router(
|
|||
}
|
||||
};
|
||||
|
||||
let kvs = kvs.with_strict_mode(address.strict);
|
||||
|
||||
let mut vars = BTreeMap::new();
|
||||
let mut stream = route_rx.into_stream();
|
||||
let configured_root = match address.auth {
|
||||
|
@ -120,15 +122,8 @@ pub(crate) fn router(
|
|||
};
|
||||
|
||||
while let Some(Some(route)) = stream.next().await {
|
||||
match super::router(
|
||||
route.request,
|
||||
&kvs,
|
||||
&configured_root,
|
||||
address.strict,
|
||||
&mut session,
|
||||
&mut vars,
|
||||
)
|
||||
.await
|
||||
match super::router(route.request, &kvs, &configured_root, &mut session, &mut vars)
|
||||
.await
|
||||
{
|
||||
Ok(value) => {
|
||||
let _ = route.response.into_send_async(Ok(value)).await;
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use crate::ctx::canceller::Canceller;
|
||||
use crate::ctx::reason::Reason;
|
||||
use crate::dbs::Notification;
|
||||
use crate::dbs::Transaction;
|
||||
use crate::err::Error;
|
||||
use crate::idx::ft::docids::DocId;
|
||||
use crate::idx::planner::executor::QueryExecutor;
|
||||
use crate::sql::value::Value;
|
||||
use crate::sql::Thing;
|
||||
use channel::Sender;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{self, Debug};
|
||||
|
@ -34,8 +36,10 @@ pub struct Context<'a> {
|
|||
cancelled: Arc<AtomicBool>,
|
||||
// A collection of read only values stored in this context.
|
||||
values: HashMap<Cow<'static, str>, Cow<'a, Value>>,
|
||||
// An optional transaction
|
||||
// Stores the current transaction if available
|
||||
transaction: Option<Transaction>,
|
||||
// Stores the notification channel if available
|
||||
notifications: Option<Sender<Notification>>,
|
||||
// An optional query executor
|
||||
query_executors: Option<Arc<HashMap<String, QueryExecutor>>>,
|
||||
// An optional record id
|
||||
|
@ -74,6 +78,7 @@ impl<'a> Context<'a> {
|
|||
deadline: None,
|
||||
cancelled: Arc::new(AtomicBool::new(false)),
|
||||
transaction: None,
|
||||
notifications: None,
|
||||
query_executors: None,
|
||||
thing: None,
|
||||
doc_id: None,
|
||||
|
@ -89,6 +94,7 @@ impl<'a> Context<'a> {
|
|||
deadline: parent.deadline,
|
||||
cancelled: Arc::new(AtomicBool::new(false)),
|
||||
transaction: parent.transaction.clone(),
|
||||
notifications: parent.notifications.clone(),
|
||||
query_executors: parent.query_executors.clone(),
|
||||
thing: parent.thing,
|
||||
doc_id: parent.doc_id,
|
||||
|
@ -96,6 +102,16 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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)
|
||||
where
|
||||
K: Into<Cow<'static, str>>,
|
||||
V: Into<Cow<'a, Value>>,
|
||||
{
|
||||
self.values.insert(key.into(), value.into());
|
||||
}
|
||||
|
||||
/// Add cancellation to the context. The value that is returned will cancel
|
||||
/// the context and it's children once called.
|
||||
pub fn add_cancel(&mut self) -> Canceller {
|
||||
|
@ -118,10 +134,24 @@ impl<'a> Context<'a> {
|
|||
self.add_deadline(Instant::now() + timeout)
|
||||
}
|
||||
|
||||
/// Add the current transaction to the context, so that it can be fetched
|
||||
/// where necessary, including inside the query planner.
|
||||
pub fn add_transaction(&mut self, txn: Option<&Transaction>) {
|
||||
if let Some(txn) = txn {
|
||||
self.transaction = Some(txn.clone());
|
||||
}
|
||||
self.transaction = txn.cloned()
|
||||
}
|
||||
|
||||
/// Add the LIVE query notification channel to the context, so that we
|
||||
/// can send notifications to any subscribers.
|
||||
pub fn add_notifications(&mut self, chn: Option<&Sender<Notification>>) {
|
||||
self.notifications = chn.cloned()
|
||||
}
|
||||
|
||||
/// Add a cursor document to this context.
|
||||
/// Usage: A new child context is created by an iterator for each document.
|
||||
/// The iterator sets the value of the current document (known as cursor document).
|
||||
/// The cursor document is copied do the child contexts.
|
||||
pub fn add_cursor_doc(&mut self, doc: &'a Value) {
|
||||
self.cursor_doc = Some(doc);
|
||||
}
|
||||
|
||||
pub fn add_thing(&mut self, thing: &'a Thing) {
|
||||
|
@ -132,29 +162,11 @@ impl<'a> Context<'a> {
|
|||
self.doc_id = Some(doc_id);
|
||||
}
|
||||
|
||||
/// Add a cursor document to this context.
|
||||
/// Usage: A new child context is created by an iterator for each document.
|
||||
/// The iterator sets the value of the current document (known as cursor document).
|
||||
/// The cursor document is copied do the child contexts.
|
||||
pub(crate) fn add_cursor_doc(&mut self, doc: &'a Value) {
|
||||
self.cursor_doc = Some(doc);
|
||||
}
|
||||
|
||||
/// Set the query executors
|
||||
pub(crate) fn set_query_executors(&mut self, executors: HashMap<String, QueryExecutor>) {
|
||||
self.query_executors = Some(Arc::new(executors));
|
||||
}
|
||||
|
||||
/// 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)
|
||||
where
|
||||
K: Into<Cow<'static, str>>,
|
||||
V: Into<Cow<'a, Value>>,
|
||||
{
|
||||
self.values.insert(key.into(), value.into());
|
||||
}
|
||||
|
||||
/// Get the timeout for this operation, if any. This is useful for
|
||||
/// checking if a long job should be started or not.
|
||||
pub fn timeout(&self) -> Option<Duration> {
|
||||
|
@ -164,10 +176,11 @@ impl<'a> Context<'a> {
|
|||
/// Returns a transaction if any.
|
||||
/// Otherwise it fails by returning a Error::NoTx error.
|
||||
pub fn try_clone_transaction(&self) -> Result<Transaction, Error> {
|
||||
match &self.transaction {
|
||||
None => Err(Error::NoTx),
|
||||
Some(txn) => Ok(txn.clone()),
|
||||
}
|
||||
self.transaction.clone().ok_or(Error::Unreachable)
|
||||
}
|
||||
|
||||
pub fn notifications(&self) -> Option<Sender<Notification>> {
|
||||
self.notifications.clone()
|
||||
}
|
||||
|
||||
pub fn thing(&self) -> Option<&Thing> {
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::sql::paths::NS;
|
|||
use crate::sql::query::Query;
|
||||
use crate::sql::statement::Statement;
|
||||
use crate::sql::value::Value;
|
||||
use channel::{Receiver, Sender};
|
||||
use channel::Receiver;
|
||||
use futures::lock::Mutex;
|
||||
use std::sync::Arc;
|
||||
use tracing::instrument;
|
||||
|
@ -122,7 +122,7 @@ impl<'a> Executor<'a> {
|
|||
}
|
||||
|
||||
/// Consume the live query notifications
|
||||
async fn clear(&self, _: Sender<Notification>, rcv: Receiver<Notification>) {
|
||||
async fn clear(&self, _: &Context<'_>, rcv: Receiver<Notification>) {
|
||||
while rcv.try_recv().is_ok() {
|
||||
// Ignore notification
|
||||
}
|
||||
|
@ -130,9 +130,15 @@ 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, chn: Sender<Notification>, rcv: Receiver<Notification>) {
|
||||
while let Ok(v) = rcv.try_recv() {
|
||||
let _ = chn.send(v).await;
|
||||
async fn flush(&self, ctx: &Context<'_>, rcv: Receiver<Notification>) {
|
||||
if let Some(chn) = ctx.notifications() {
|
||||
while let Ok(v) = rcv.try_recv() {
|
||||
let _ = chn.send(v).await;
|
||||
}
|
||||
} else {
|
||||
while rcv.try_recv().is_ok() {
|
||||
// Ignore notification
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,14 +146,14 @@ impl<'a> Executor<'a> {
|
|||
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);
|
||||
opt.ns = Some(ns.into());
|
||||
opt.set_ns(Some(ns.into()));
|
||||
}
|
||||
|
||||
async fn set_db(&self, ctx: &mut Context<'_>, opt: &mut Options, db: &str) {
|
||||
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);
|
||||
opt.db = Some(db.into());
|
||||
opt.set_db(Some(db.into()));
|
||||
}
|
||||
|
||||
#[instrument(name = "executor", skip_all)]
|
||||
|
@ -157,12 +163,10 @@ impl<'a> Executor<'a> {
|
|||
opt: Options,
|
||||
qry: Query,
|
||||
) -> Result<Vec<Response>, Error> {
|
||||
// Take the notification channel
|
||||
let chn = opt.sender.clone();
|
||||
// Create a notification channel
|
||||
let (send, recv) = channel::unbounded();
|
||||
// Swap the notification channel
|
||||
let mut opt = opt.sender(send);
|
||||
// Set the notification channel
|
||||
let mut opt = opt.new_with_sender(send);
|
||||
// Initialise buffer of responses
|
||||
let mut buf: Vec<Response> = vec![];
|
||||
// Initialise array of responses
|
||||
|
@ -191,11 +195,11 @@ impl<'a> Executor<'a> {
|
|||
stm.name.0.make_ascii_uppercase();
|
||||
// Process the option
|
||||
opt = match stm.name.0.as_str() {
|
||||
"FIELDS" => opt.fields(stm.what),
|
||||
"EVENTS" => opt.events(stm.what),
|
||||
"TABLES" => opt.tables(stm.what),
|
||||
"IMPORT" => opt.import(stm.what),
|
||||
"FORCE" => opt.force(stm.what),
|
||||
"FIELDS" => opt.with_fields(stm.what),
|
||||
"EVENTS" => opt.with_events(stm.what),
|
||||
"TABLES" => opt.with_tables(stm.what),
|
||||
"IMPORT" => opt.with_import(stm.what),
|
||||
"FORCE" => opt.with_force(stm.what),
|
||||
_ => break,
|
||||
};
|
||||
// Continue
|
||||
|
@ -209,7 +213,7 @@ impl<'a> Executor<'a> {
|
|||
// Cancel a running transaction
|
||||
Statement::Cancel(_) => {
|
||||
self.cancel(true).await;
|
||||
self.clear(chn.clone(), recv.clone()).await;
|
||||
self.clear(&ctx, recv.clone()).await;
|
||||
buf = buf.into_iter().map(|v| self.buf_cancel(v)).collect();
|
||||
out.append(&mut buf);
|
||||
debug_assert!(self.txn.is_none(), "cancel(true) should have unset txn");
|
||||
|
@ -220,7 +224,7 @@ impl<'a> Executor<'a> {
|
|||
Statement::Commit(_) => {
|
||||
let commit_error = self.commit(true).await.err();
|
||||
buf = buf.into_iter().map(|v| self.buf_commit(v, &commit_error)).collect();
|
||||
self.flush(chn.clone(), recv.clone()).await;
|
||||
self.flush(&ctx, recv.clone()).await;
|
||||
out.append(&mut buf);
|
||||
debug_assert!(self.txn.is_none(), "commit(true) should have unset txn");
|
||||
self.txn = None;
|
||||
|
@ -235,7 +239,7 @@ impl<'a> Executor<'a> {
|
|||
Auth::Ns(v) if v == ns => self.set_ns(&mut ctx, &mut opt, ns).await,
|
||||
Auth::Db(v, _) if v == ns => self.set_ns(&mut ctx, &mut opt, ns).await,
|
||||
_ => {
|
||||
opt.ns = None;
|
||||
opt.set_ns(None);
|
||||
return Err(Error::NsNotAllowed {
|
||||
ns: ns.to_owned(),
|
||||
});
|
||||
|
@ -249,7 +253,7 @@ impl<'a> Executor<'a> {
|
|||
Auth::Ns(_) => self.set_db(&mut ctx, &mut opt, db).await,
|
||||
Auth::Db(_, v) if v == db => self.set_db(&mut ctx, &mut opt, db).await,
|
||||
_ => {
|
||||
opt.db = None;
|
||||
opt.set_db(None);
|
||||
return Err(Error::DbNotAllowed {
|
||||
db: db.to_owned(),
|
||||
});
|
||||
|
@ -293,20 +297,20 @@ impl<'a> Executor<'a> {
|
|||
match self.commit(loc).await {
|
||||
Err(e) => {
|
||||
// Clear live query notifications
|
||||
self.clear(chn.clone(), recv.clone()).await;
|
||||
self.clear(&ctx, recv.clone()).await;
|
||||
Err(Error::QueryNotExecutedDetail {
|
||||
message: e.to_string(),
|
||||
})
|
||||
}
|
||||
Ok(_) => {
|
||||
// Flush live query notifications
|
||||
self.flush(chn.clone(), recv.clone()).await;
|
||||
self.flush(&ctx, recv.clone()).await;
|
||||
Ok(Value::None)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.cancel(loc).await;
|
||||
self.clear(chn.clone(), recv.clone()).await;
|
||||
self.clear(&ctx, recv.clone()).await;
|
||||
Ok(Value::None)
|
||||
}
|
||||
}
|
||||
|
@ -365,21 +369,21 @@ impl<'a> Executor<'a> {
|
|||
if res.is_ok() && stm.writeable() {
|
||||
if let Err(e) = self.commit(loc).await {
|
||||
// Clear live query notification details
|
||||
self.clear(chn.clone(), recv.clone()).await;
|
||||
self.clear(&ctx, recv.clone()).await;
|
||||
// The commit failed
|
||||
Err(Error::QueryNotExecutedDetail {
|
||||
message: e.to_string(),
|
||||
})
|
||||
} else {
|
||||
// Flush the live query change notifications
|
||||
self.flush(chn.clone(), recv.clone()).await;
|
||||
self.flush(&ctx, recv.clone()).await;
|
||||
// Successful, committed result
|
||||
res
|
||||
}
|
||||
} else {
|
||||
self.cancel(loc).await;
|
||||
// Clear live query notification details
|
||||
self.clear(chn.clone(), recv.clone()).await;
|
||||
self.clear(&ctx, recv.clone()).await;
|
||||
// Return an error
|
||||
res
|
||||
}
|
||||
|
|
|
@ -13,19 +13,18 @@ use uuid::Uuid;
|
|||
/// version to retrieve, whether futures should be processed, and
|
||||
/// whether field/event/table queries should be processed (useful
|
||||
/// when importing data, where these queries might fail).
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Options {
|
||||
/// Current Node ID
|
||||
pub id: Arc<Uuid>,
|
||||
id: Option<Uuid>,
|
||||
/// Currently selected NS
|
||||
pub ns: Option<Arc<str>>,
|
||||
ns: Option<Arc<str>>,
|
||||
/// Currently selected DB
|
||||
pub db: Option<Arc<str>>,
|
||||
/// Connection authentication data
|
||||
pub auth: Arc<Auth>,
|
||||
db: Option<Arc<str>>,
|
||||
/// Approximately how large is the current call stack?
|
||||
dive: u8,
|
||||
/// Connection authentication data
|
||||
pub auth: Arc<Auth>,
|
||||
/// Whether live queries are allowed?
|
||||
pub live: bool,
|
||||
/// Should we force tables/events to re-run?
|
||||
|
@ -44,21 +43,21 @@ pub struct Options {
|
|||
pub indexes: bool,
|
||||
/// Should we process function futures?
|
||||
pub futures: bool,
|
||||
///
|
||||
pub sender: Sender<Notification>,
|
||||
/// The channel over which we send notifications
|
||||
pub sender: Option<Sender<Notification>>,
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
fn default() -> Self {
|
||||
Options::new(Arc::new(Uuid::new_v4()), channel::unbounded().0, Arc::new(Auth::No))
|
||||
Options::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Options {
|
||||
/// Create a new Options object
|
||||
pub fn new(id: Arc<Uuid>, send: Sender<Notification>, auth: Arc<Auth>) -> Options {
|
||||
pub fn new() -> Options {
|
||||
Options {
|
||||
id,
|
||||
id: None,
|
||||
ns: None,
|
||||
db: None,
|
||||
dive: 0,
|
||||
|
@ -71,37 +70,252 @@ impl Options {
|
|||
tables: true,
|
||||
indexes: true,
|
||||
futures: false,
|
||||
sender: send,
|
||||
auth,
|
||||
sender: None,
|
||||
auth: Arc::new(Auth::No),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get current Node ID
|
||||
pub fn id(&self) -> &Uuid {
|
||||
self.id.as_ref()
|
||||
// --------------------------------------------------
|
||||
|
||||
/// Specify which Namespace should be used for
|
||||
/// code which uses this `Options` object.
|
||||
pub fn set_ns(&mut self, ns: Option<Arc<str>>) {
|
||||
self.ns = ns
|
||||
}
|
||||
|
||||
/// Get currently selected NS
|
||||
pub fn ns(&self) -> &str {
|
||||
self.ns.as_ref().unwrap()
|
||||
/// Specify which Database should be used for
|
||||
/// code which uses this `Options` object.
|
||||
pub fn set_db(&mut self, db: Option<Arc<str>>) {
|
||||
self.db = db
|
||||
}
|
||||
|
||||
/// Get currently selected DB
|
||||
pub fn db(&self) -> &str {
|
||||
self.db.as_ref().unwrap()
|
||||
// --------------------------------------------------
|
||||
|
||||
/// Set the Node ID for subsequent code which uses
|
||||
/// this `Options`, with support for chaining.
|
||||
pub fn with_id(mut self, id: Uuid) -> Self {
|
||||
self.id = Some(id);
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify which Namespace should be used for code which
|
||||
/// uses this `Options`, with support for chaining.
|
||||
pub fn with_ns(mut self, ns: Option<Arc<str>>) -> Self {
|
||||
self.ns = ns;
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify which Database should be used for code which
|
||||
/// uses this `Options`, with support for chaining.
|
||||
pub fn with_db(mut self, db: Option<Arc<str>>) -> Self {
|
||||
self.db = db;
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify the authentication options for subsequent
|
||||
/// code which uses this `Options`, with chaining.
|
||||
pub fn with_auth(mut self, auth: Arc<Auth>) -> Self {
|
||||
self.auth = auth;
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify whether live queries are supported for
|
||||
/// code which uses this `Options`, with chaining.
|
||||
pub fn with_live(mut self, live: bool) -> Self {
|
||||
self.live = live;
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify whether permissions should be run for
|
||||
/// code which uses this `Options`, with chaining.
|
||||
pub fn with_perms(mut self, perms: bool) -> Self {
|
||||
self.perms = perms;
|
||||
self
|
||||
}
|
||||
|
||||
///
|
||||
pub fn with_force(mut self, force: bool) -> Self {
|
||||
self.force = force;
|
||||
self
|
||||
}
|
||||
|
||||
///
|
||||
pub fn with_strict(mut self, strict: bool) -> Self {
|
||||
self.strict = strict;
|
||||
self
|
||||
}
|
||||
|
||||
///
|
||||
pub fn with_fields(mut self, fields: bool) -> Self {
|
||||
self.fields = fields;
|
||||
self
|
||||
}
|
||||
|
||||
///
|
||||
pub fn with_events(mut self, events: bool) -> Self {
|
||||
self.events = events;
|
||||
self
|
||||
}
|
||||
|
||||
///
|
||||
pub fn with_tables(mut self, tables: bool) -> Self {
|
||||
self.tables = tables;
|
||||
self
|
||||
}
|
||||
|
||||
///
|
||||
pub fn with_indexes(mut self, indexes: bool) -> Self {
|
||||
self.indexes = indexes;
|
||||
self
|
||||
}
|
||||
|
||||
///
|
||||
pub fn with_futures(mut self, futures: bool) -> Self {
|
||||
self.futures = futures;
|
||||
self
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn with_import(mut self, import: bool) -> Self {
|
||||
self.fields = !import;
|
||||
self.events = !import;
|
||||
self.tables = !import;
|
||||
self
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn new_with_perms(&self, perms: bool) -> Self {
|
||||
Self {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
perms,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn new_with_force(&self, force: bool) -> Self {
|
||||
Self {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
force,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn new_with_strict(&self, strict: bool) -> Self {
|
||||
Self {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
strict,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn new_with_fields(&self, fields: bool) -> Self {
|
||||
Self {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
fields,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn new_with_events(&self, events: bool) -> Self {
|
||||
Self {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
events,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn new_with_tables(&self, tables: bool) -> Self {
|
||||
Self {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
tables,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn new_with_indexes(&self, indexes: bool) -> Self {
|
||||
Self {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
indexes,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn new_with_futures(&self, futures: bool) -> Self {
|
||||
Self {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
futures,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn new_with_import(&self, import: bool) -> Self {
|
||||
Self {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
fields: !import,
|
||||
events: !import,
|
||||
tables: !import,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn new_with_sender(&self, sender: Sender<Notification>) -> Self {
|
||||
Self {
|
||||
auth: self.auth.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
sender: Some(sender),
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a function/subquery/future/etc.
|
||||
///
|
||||
/// The parameter is the approximate cost of the operation (more concretely, the size of the
|
||||
/// stack frame it uses relative to a simple function call). When in doubt, use a value of 1.
|
||||
pub fn dive(&self, cost: u8) -> Result<Options, Error> {
|
||||
pub fn dive(&self, cost: u8) -> Result<Self, Error> {
|
||||
let dive = self.dive.saturating_add(cost);
|
||||
if dive <= *cnf::MAX_COMPUTATION_DEPTH {
|
||||
Ok(Options {
|
||||
Ok(Self {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
dive,
|
||||
|
@ -112,138 +326,26 @@ impl Options {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn force(&self, v: bool) -> Options {
|
||||
Options {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
force: v,
|
||||
..*self
|
||||
}
|
||||
// --------------------------------------------------
|
||||
|
||||
/// Get current Node ID
|
||||
pub fn id(&self) -> Result<Uuid, Error> {
|
||||
self.id.ok_or(Error::Unreachable)
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn perms(&self, v: bool) -> Options {
|
||||
Options {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
perms: v,
|
||||
..*self
|
||||
}
|
||||
/// Get currently selected NS
|
||||
pub fn ns(&self) -> &str {
|
||||
self.ns.as_ref().map(AsRef::as_ref).unwrap()
|
||||
// self.ns.as_ref().map(AsRef::as_ref).ok_or(Error::Unreachable)
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn fields(&self, v: bool) -> Options {
|
||||
Options {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
fields: v,
|
||||
..*self
|
||||
}
|
||||
/// Get currently selected DB
|
||||
pub fn db(&self) -> &str {
|
||||
self.db.as_ref().map(AsRef::as_ref).unwrap()
|
||||
// self.db.as_ref().map(AsRef::as_ref).ok_or(Error::Unreachable)
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn events(&self, v: bool) -> Options {
|
||||
Options {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
events: v,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn tables(&self, v: bool) -> Options {
|
||||
Options {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
tables: v,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn indexes(&self, v: bool) -> Options {
|
||||
Options {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
indexes: v,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn import(&self, v: bool) -> Options {
|
||||
Options {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
fields: !v,
|
||||
events: !v,
|
||||
tables: !v,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn strict(&self, v: bool) -> Options {
|
||||
Options {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
strict: v,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn futures(&self, v: bool) -> Options {
|
||||
Options {
|
||||
sender: self.sender.clone(),
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
futures: v,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Options object for a subquery
|
||||
pub fn sender(&self, v: Sender<Notification>) -> Options {
|
||||
Options {
|
||||
auth: self.auth.clone(),
|
||||
id: self.id.clone(),
|
||||
ns: self.ns.clone(),
|
||||
db: self.db.clone(),
|
||||
sender: v,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether realtime queries are supported
|
||||
/// Check whether this request supports realtime queries
|
||||
pub fn realtime(&self) -> Result<(), Error> {
|
||||
if !self.live {
|
||||
return Err(Error::RealtimeDisabled);
|
||||
|
|
|
@ -90,6 +90,10 @@ impl Session {
|
|||
pub(crate) fn db(&self) -> Option<Arc<str>> {
|
||||
self.db.as_deref().map(Into::into)
|
||||
}
|
||||
/// Checks if live queries are allowed
|
||||
pub(crate) fn live(&self) -> bool {
|
||||
self.rt
|
||||
}
|
||||
/// Convert a session into a runtime
|
||||
pub(crate) fn context<'a>(&self, mut ctx: Context<'a>) -> Context<'a> {
|
||||
// Add auth data
|
||||
|
|
|
@ -3,11 +3,10 @@ use crate::dbs::{Auth, Options};
|
|||
use crate::kvs::Datastore;
|
||||
use futures::lock::Mutex;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub async fn mock<'a>() -> (Context<'a>, Options) {
|
||||
let mut ctx = Context::default();
|
||||
let opt = Options::new(Arc::new(Uuid::new_v4()), channel::unbounded().0, Arc::new(Auth::Kv));
|
||||
let opt = Options::default().with_auth(Arc::new(Auth::Kv));
|
||||
let kvs = Datastore::new("memory").await.unwrap();
|
||||
let txn = kvs.transaction(true, false).await.unwrap();
|
||||
let txn = Arc::new(Mutex::new(txn));
|
||||
|
|
|
@ -36,7 +36,7 @@ impl<'a> Document<'a> {
|
|||
Permission::Full => return Ok(()),
|
||||
Permission::Specific(e) => {
|
||||
// Disable permissions
|
||||
let opt = &opt.perms(false);
|
||||
let opt = &opt.new_with_perms(false);
|
||||
let mut ctx = Context::new(ctx);
|
||||
ctx.add_cursor_doc(&self.current);
|
||||
// Process the PERMISSION clause
|
||||
|
|
|
@ -22,7 +22,7 @@ impl<'a> Document<'a> {
|
|||
return Ok(());
|
||||
}
|
||||
// Don't run permissions
|
||||
let opt = &opt.perms(false);
|
||||
let opt = &opt.new_with_perms(false);
|
||||
// Clone transaction
|
||||
let txn = ctx.try_clone_transaction()?;
|
||||
// Loop through all event statements
|
||||
|
|
|
@ -112,7 +112,7 @@ impl<'a> Document<'a> {
|
|||
Permission::None => val = old,
|
||||
Permission::Specific(e) => {
|
||||
// Disable permissions
|
||||
let opt = &opt.perms(false);
|
||||
let opt = &opt.new_with_perms(false);
|
||||
// Configure the context
|
||||
let mut ctx = Context::new(ctx);
|
||||
ctx.add_value("input", &inp);
|
||||
|
|
|
@ -19,7 +19,7 @@ impl<'a> Document<'a> {
|
|||
opt: &Options,
|
||||
_stm: &Statement<'_>,
|
||||
) -> Result<(), Error> {
|
||||
// Check events
|
||||
// Check indexes
|
||||
if !opt.indexes {
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
@ -21,57 +21,59 @@ impl<'a> Document<'a> {
|
|||
// Clone transaction
|
||||
let txn = ctx.try_clone_transaction()?;
|
||||
// Get the record id
|
||||
let id = self.id.as_ref().unwrap();
|
||||
// Loop through all index statements
|
||||
for lv in self.lv(opt, &txn).await?.iter() {
|
||||
// Create a new statement
|
||||
let lq = Statement::from(lv);
|
||||
// Check LIVE SELECT where condition
|
||||
if self.check(ctx, opt, &lq).await.is_err() {
|
||||
continue;
|
||||
}
|
||||
// Check what type of data change this is
|
||||
if stm.is_delete() {
|
||||
// Send a DELETE notification
|
||||
if opt.id() == &lv.node.0 {
|
||||
let thing = (*id).clone();
|
||||
opt.sender
|
||||
.send(Notification {
|
||||
let rid = self.id.as_ref().unwrap();
|
||||
// Check if we can send notifications
|
||||
if let Some(chn) = &opt.sender {
|
||||
// Clone the sending channel
|
||||
let chn = chn.clone();
|
||||
// Loop through all index statements
|
||||
for lv in self.lv(opt, &txn).await?.iter() {
|
||||
// Create a new statement
|
||||
let lq = Statement::from(lv);
|
||||
// Check LIVE SELECT where condition
|
||||
if self.check(ctx, opt, &lq).await.is_err() {
|
||||
continue;
|
||||
}
|
||||
// Check what type of data change this is
|
||||
if stm.is_delete() {
|
||||
// Send a DELETE notification
|
||||
if opt.id()? == lv.node.0 {
|
||||
let thing = (*rid).clone();
|
||||
chn.send(Notification {
|
||||
id: lv.id.0,
|
||||
action: Action::Delete,
|
||||
result: Value::Thing(thing),
|
||||
})
|
||||
.await?;
|
||||
} else {
|
||||
// TODO: Send to storage
|
||||
}
|
||||
} else if self.is_new() {
|
||||
// Send a CREATE notification
|
||||
if opt.id() == &lv.node.0 {
|
||||
opt.sender
|
||||
.send(Notification {
|
||||
} else {
|
||||
// TODO: Send to storage
|
||||
}
|
||||
} else if self.is_new() {
|
||||
// Send a CREATE notification
|
||||
if opt.id()? == lv.node.0 {
|
||||
chn.send(Notification {
|
||||
id: lv.id.0,
|
||||
action: Action::Create,
|
||||
result: self.pluck(ctx, opt, &lq).await?,
|
||||
})
|
||||
.await?;
|
||||
} else {
|
||||
// TODO: Send to storage
|
||||
}
|
||||
} else {
|
||||
// TODO: Send to storage
|
||||
}
|
||||
} else {
|
||||
// Send a UPDATE notification
|
||||
if opt.id() == &lv.node.0 {
|
||||
opt.sender
|
||||
.send(Notification {
|
||||
// Send a UPDATE notification
|
||||
if opt.id()? == lv.node.0 {
|
||||
chn.send(Notification {
|
||||
id: lv.id.0,
|
||||
action: Action::Update,
|
||||
result: self.pluck(ctx, opt, &lq).await?,
|
||||
})
|
||||
.await?;
|
||||
} else {
|
||||
// TODO: Send to storage
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// TODO: Send to storage
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
// Carry on
|
||||
Ok(())
|
||||
|
|
|
@ -17,7 +17,7 @@ impl<'a> Document<'a> {
|
|||
stm: &Statement<'_>,
|
||||
) -> Result<Value, Error> {
|
||||
// Ensure futures are run
|
||||
let opt = &opt.futures(true);
|
||||
let opt = &opt.new_with_futures(true);
|
||||
// Process the desired output
|
||||
let mut out = match stm.output() {
|
||||
Some(v) => match v {
|
||||
|
@ -93,7 +93,7 @@ impl<'a> Document<'a> {
|
|||
Permission::None => out.del(ctx, opt, k).await?,
|
||||
Permission::Specific(e) => {
|
||||
// Disable permissions
|
||||
let opt = &opt.perms(false);
|
||||
let opt = &opt.new_with_perms(false);
|
||||
// Get the current value
|
||||
let val = self.current.pick(k);
|
||||
// Configure the context
|
||||
|
|
|
@ -35,7 +35,7 @@ impl<'a> Document<'a> {
|
|||
opt: &Options,
|
||||
stm: &Statement<'_>,
|
||||
) -> Result<(), Error> {
|
||||
// Check events
|
||||
// Check tables
|
||||
if !opt.tables {
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ impl<'a> Document<'a> {
|
|||
return Ok(());
|
||||
}
|
||||
// Don't run permissions
|
||||
let opt = &opt.perms(false);
|
||||
let opt = &opt.new_with_perms(false);
|
||||
// Get the record id
|
||||
let rid = self.id.as_ref().unwrap();
|
||||
// Get the query action
|
||||
|
|
|
@ -22,6 +22,10 @@ pub enum Error {
|
|||
#[error("Conditional clause is not truthy")]
|
||||
Ignore,
|
||||
|
||||
/// The database encountered unreachable logic
|
||||
#[error("The database encountered unreachable logic")]
|
||||
Unreachable,
|
||||
|
||||
/// There was a problem with the underlying datastore
|
||||
#[error("There was a problem with the underlying datastore: {0}")]
|
||||
Ds(String),
|
||||
|
@ -62,10 +66,6 @@ pub enum Error {
|
|||
#[error("Transaction is too large")]
|
||||
TxTooLarge,
|
||||
|
||||
/// The context does have any transaction
|
||||
#[error("No transaction")]
|
||||
NoTx,
|
||||
|
||||
/// No namespace has been selected
|
||||
#[error("Specify a namespace to use")]
|
||||
NsEmpty,
|
||||
|
|
|
@ -343,7 +343,7 @@ mod tests {
|
|||
format!("RETURN function() {{ return typeof surrealdb.functions.{name}; }}");
|
||||
let dbs = crate::kvs::Datastore::new("memory").await.unwrap();
|
||||
let ses = crate::dbs::Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, false).await.unwrap();
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await.unwrap();
|
||||
let tmp = res.remove(0).result.unwrap();
|
||||
if tmp == Value::from("object") {
|
||||
// Assume this function is superseded by a module of the same name.
|
||||
|
|
|
@ -16,7 +16,6 @@ use std::sync::Arc;
|
|||
pub async fn signin(
|
||||
kvs: &Datastore,
|
||||
configured_root: &Option<Root<'_>>,
|
||||
strict: bool,
|
||||
session: &mut Session,
|
||||
vars: Object,
|
||||
) -> Result<Option<String>, Error> {
|
||||
|
@ -32,7 +31,7 @@ pub async fn signin(
|
|||
let db = db.to_raw_string();
|
||||
let sc = sc.to_raw_string();
|
||||
// Attempt to signin to specified scope
|
||||
super::signin::sc(kvs, strict, session, ns, db, sc, vars).await
|
||||
super::signin::sc(kvs, session, ns, db, sc, vars).await
|
||||
}
|
||||
(Some(ns), Some(db), None) => {
|
||||
// Get the provided user and pass
|
||||
|
@ -98,7 +97,6 @@ pub async fn signin(
|
|||
|
||||
pub async fn sc(
|
||||
kvs: &Datastore,
|
||||
strict: bool,
|
||||
session: &mut Session,
|
||||
ns: String,
|
||||
db: String,
|
||||
|
@ -118,7 +116,7 @@ pub async fn sc(
|
|||
// Setup the query session
|
||||
let sess = Session::for_db(&ns, &db);
|
||||
// Compute the value with the params
|
||||
match kvs.compute(val, &sess, vars, strict).await {
|
||||
match kvs.compute(val, &sess, vars).await {
|
||||
// The signin value succeeded
|
||||
Ok(val) => match val.record() {
|
||||
// There is a record returned
|
||||
|
|
|
@ -12,7 +12,6 @@ use std::sync::Arc;
|
|||
|
||||
pub async fn signup(
|
||||
kvs: &Datastore,
|
||||
strict: bool,
|
||||
session: &mut Session,
|
||||
vars: Object,
|
||||
) -> Result<Option<String>, Error> {
|
||||
|
@ -28,7 +27,7 @@ pub async fn signup(
|
|||
let db = db.to_raw_string();
|
||||
let sc = sc.to_raw_string();
|
||||
// Attempt to signin to specified scope
|
||||
super::signup::sc(kvs, strict, session, ns, db, sc, vars).await
|
||||
super::signup::sc(kvs, session, ns, db, sc, vars).await
|
||||
}
|
||||
_ => Err(Error::InvalidAuth),
|
||||
}
|
||||
|
@ -36,7 +35,6 @@ pub async fn signup(
|
|||
|
||||
pub async fn sc(
|
||||
kvs: &Datastore,
|
||||
strict: bool,
|
||||
session: &mut Session,
|
||||
ns: String,
|
||||
db: String,
|
||||
|
@ -56,7 +54,7 @@ pub async fn sc(
|
|||
// Setup the query session
|
||||
let sess = Session::for_db(&ns, &db);
|
||||
// Compute the value with the params
|
||||
match kvs.compute(val, &sess, vars, strict).await {
|
||||
match kvs.compute(val, &sess, vars).await {
|
||||
// The signin value succeeded
|
||||
Ok(val) => match val.record() {
|
||||
// There is a record returned
|
||||
|
|
|
@ -10,6 +10,7 @@ pub struct Cl {
|
|||
_a: u8,
|
||||
_b: u8,
|
||||
_c: u8,
|
||||
#[serde(with = "uuid::serde::compact")]
|
||||
pub nd: Uuid,
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ pub struct Hb {
|
|||
_c: u8,
|
||||
_d: u8,
|
||||
pub hb: Timestamp,
|
||||
#[serde(with = "uuid::serde::compact")]
|
||||
pub nd: Uuid,
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,12 @@ pub struct Lq<'a> {
|
|||
_f: u8,
|
||||
_g: u8,
|
||||
_h: u8,
|
||||
#[serde(with = "uuid::serde::compact")]
|
||||
pub lq: Uuid,
|
||||
}
|
||||
|
||||
pub fn new<'a>(nd: &Uuid, ns: &'a str, db: &'a str, lq: &Uuid) -> Lq<'a> {
|
||||
Lq::new(nd.to_owned(), ns, db, lq.to_owned())
|
||||
pub fn new<'a>(nd: Uuid, ns: &'a str, db: &'a str, lq: Uuid) -> Lq<'a> {
|
||||
Lq::new(nd, ns, db, lq)
|
||||
}
|
||||
|
||||
impl<'a> Lq<'a> {
|
||||
|
|
|
@ -14,11 +14,12 @@ pub struct Lv<'a> {
|
|||
_d: u8,
|
||||
_e: u8,
|
||||
_f: u8,
|
||||
#[serde(with = "uuid::serde::compact")]
|
||||
pub lv: Uuid,
|
||||
}
|
||||
|
||||
pub fn new<'a>(ns: &'a str, db: &'a str, tb: &'a str, lv: &Uuid) -> Lv<'a> {
|
||||
Lv::new(ns, db, tb, lv.to_owned())
|
||||
pub fn new<'a>(ns: &'a str, db: &'a str, tb: &'a str, lv: Uuid) -> Lv<'a> {
|
||||
Lv::new(ns, db, tb, lv)
|
||||
}
|
||||
|
||||
pub fn prefix(ns: &str, db: &str, tb: &str) -> Vec<u8> {
|
||||
|
|
|
@ -23,11 +23,18 @@ use uuid::Uuid;
|
|||
/// The underlying datastore instance which stores the dataset.
|
||||
#[allow(dead_code)]
|
||||
pub struct Datastore {
|
||||
pub(super) id: Arc<Uuid>,
|
||||
pub(super) inner: Inner,
|
||||
pub(super) send: Sender<Notification>,
|
||||
pub(super) recv: Receiver<Notification>,
|
||||
// The inner datastore type
|
||||
inner: Inner,
|
||||
// The unique id of this datastore, used in notifications
|
||||
id: Uuid,
|
||||
// Whether this datastore runs in strict mode by default
|
||||
strict: bool,
|
||||
// The maximum duration timeout for running multiple statements in a query
|
||||
query_timeout: Option<Duration>,
|
||||
// The maximum duration timeout for running multiple statements in a transaction
|
||||
transaction_timeout: Option<Duration>,
|
||||
// Whether this datastore enables live query notifications to subscribers
|
||||
notification_channel: Option<(Sender<Notification>, Receiver<Notification>)>,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
|
@ -209,28 +216,46 @@ impl Datastore {
|
|||
Err(Error::Ds("Unable to load the specified datastore".into()))
|
||||
}
|
||||
};
|
||||
// Create a live query notification channel
|
||||
let (send, recv) = channel::bounded(100);
|
||||
// Set the properties on the datastore
|
||||
inner.map(|inner| Self {
|
||||
id: Arc::new(Uuid::new_v4()),
|
||||
id: Uuid::default(),
|
||||
inner,
|
||||
send,
|
||||
recv,
|
||||
strict: false,
|
||||
query_timeout: None,
|
||||
transaction_timeout: None,
|
||||
notification_channel: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Set global query timeout
|
||||
pub fn query_timeout(mut self, duration: Option<Duration>) -> Self {
|
||||
/// Specify whether this Datastore should run in strict mode
|
||||
pub fn with_strict_mode(mut self, strict: bool) -> Self {
|
||||
self.strict = strict;
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify whether this datastore should enable live query notifications
|
||||
pub fn with_notifications(mut self) -> Self {
|
||||
self.notification_channel = Some(channel::bounded(100));
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a global query timeout for this Datastore
|
||||
pub fn with_query_timeout(mut self, duration: Option<Duration>) -> Self {
|
||||
self.query_timeout = duration;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a global transaction timeout for this Datastore
|
||||
pub fn with_transaction_timeout(mut self, duration: Option<Duration>) -> Self {
|
||||
self.transaction_timeout = duration;
|
||||
self
|
||||
}
|
||||
|
||||
// Adds entries to the KV store indicating membership information
|
||||
pub async fn register_membership(&self) -> Result<(), Error> {
|
||||
let mut tx = self.transaction(true, false).await?;
|
||||
tx.set_cl(sql::Uuid::from(*self.id.as_ref())).await?;
|
||||
tx.set_hb(sql::Uuid::from(*self.id.as_ref())).await?;
|
||||
tx.set_cl(self.id).await?;
|
||||
tx.set_hb(self.id).await?;
|
||||
tx.commit().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -239,7 +264,7 @@ impl Datastore {
|
|||
// that the node is alive
|
||||
pub async fn heartbeat(&self) -> Result<(), Error> {
|
||||
let mut tx = self.transaction(true, false).await?;
|
||||
tx.set_hb(sql::Uuid::from(*self.id.as_ref())).await?;
|
||||
tx.set_hb(self.id).await?;
|
||||
tx.commit().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -314,7 +339,7 @@ impl Datastore {
|
|||
/// let ds = Datastore::new("memory").await?;
|
||||
/// let ses = Session::for_kv();
|
||||
/// let ast = "USE NS test DB test; SELECT * FROM person;";
|
||||
/// let res = ds.execute(ast, &ses, None, false).await?;
|
||||
/// let res = ds.execute(ast, &ses, None).await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -324,12 +349,11 @@ impl Datastore {
|
|||
txt: &str,
|
||||
sess: &Session,
|
||||
vars: Variables,
|
||||
strict: bool,
|
||||
) -> Result<Vec<Response>, Error> {
|
||||
// Parse the SQL query text
|
||||
let ast = sql::parse(txt)?;
|
||||
// Process the AST
|
||||
self.process(ast, sess, vars, strict).await
|
||||
self.process(ast, sess, vars).await
|
||||
}
|
||||
|
||||
/// Execute a pre-parsed SQL query
|
||||
|
@ -345,7 +369,7 @@ impl Datastore {
|
|||
/// let ds = Datastore::new("memory").await?;
|
||||
/// let ses = Session::for_kv();
|
||||
/// let ast = parse("USE NS test DB test; SELECT * FROM person;")?;
|
||||
/// let res = ds.process(ast, &ses, None, false).await?;
|
||||
/// let res = ds.process(ast, &ses, None).await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -355,10 +379,15 @@ impl Datastore {
|
|||
ast: Query,
|
||||
sess: &Session,
|
||||
vars: Variables,
|
||||
strict: bool,
|
||||
) -> Result<Vec<Response>, Error> {
|
||||
// Create a new query options
|
||||
let mut opt = Options::default();
|
||||
let opt = Options::default()
|
||||
.with_id(self.id)
|
||||
.with_ns(sess.ns())
|
||||
.with_db(sess.db())
|
||||
.with_live(sess.live())
|
||||
.with_auth(sess.au.clone())
|
||||
.with_strict(self.strict);
|
||||
// Create a new query executor
|
||||
let mut exe = Executor::new(self);
|
||||
// Create a default context
|
||||
|
@ -367,21 +396,14 @@ impl Datastore {
|
|||
if let Some(timeout) = self.query_timeout {
|
||||
ctx.add_timeout(timeout);
|
||||
}
|
||||
// Setup the notification channel
|
||||
if let Some(channel) = &self.notification_channel {
|
||||
ctx.add_notifications(Some(&channel.0));
|
||||
}
|
||||
// Start an execution context
|
||||
let ctx = sess.context(ctx);
|
||||
// Store the query variables
|
||||
let ctx = vars.attach(ctx)?;
|
||||
// Setup the notification channel
|
||||
opt.sender = self.send.clone();
|
||||
// Setup the auth options
|
||||
opt.auth = sess.au.clone();
|
||||
// Setup the live options
|
||||
opt.live = sess.rt;
|
||||
// Set current NS and DB
|
||||
opt.ns = sess.ns();
|
||||
opt.db = sess.db();
|
||||
// Set strict config
|
||||
opt.strict = strict;
|
||||
// Process all statements
|
||||
exe.execute(ctx, opt, ast).await
|
||||
}
|
||||
|
@ -400,7 +422,7 @@ impl Datastore {
|
|||
/// let ds = Datastore::new("memory").await?;
|
||||
/// let ses = Session::for_kv();
|
||||
/// let val = Value::Future(Box::new(Future::from(Value::Bool(true))));
|
||||
/// let res = ds.compute(val, &ses, None, false).await?;
|
||||
/// let res = ds.compute(val, &ses, None).await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -410,14 +432,19 @@ impl Datastore {
|
|||
val: Value,
|
||||
sess: &Session,
|
||||
vars: Variables,
|
||||
strict: bool,
|
||||
) -> Result<Value, Error> {
|
||||
// Create a new query options
|
||||
let opt = Options::default()
|
||||
.with_id(self.id)
|
||||
.with_ns(sess.ns())
|
||||
.with_db(sess.db())
|
||||
.with_live(sess.live())
|
||||
.with_auth(sess.au.clone())
|
||||
.with_strict(self.strict);
|
||||
// Start a new transaction
|
||||
let txn = self.transaction(val.writeable(), false).await?;
|
||||
//
|
||||
let txn = Arc::new(Mutex::new(txn));
|
||||
// Create a new query options
|
||||
let mut opt = Options::default();
|
||||
// Create a default context
|
||||
let mut ctx = Context::default();
|
||||
// Add the transaction
|
||||
|
@ -426,19 +453,14 @@ impl Datastore {
|
|||
if let Some(timeout) = self.query_timeout {
|
||||
ctx.add_timeout(timeout);
|
||||
}
|
||||
// Setup the notification channel
|
||||
if let Some(channel) = &self.notification_channel {
|
||||
ctx.add_notifications(Some(&channel.0));
|
||||
}
|
||||
// Start an execution context
|
||||
let ctx = sess.context(ctx);
|
||||
// Store the query variables
|
||||
let ctx = vars.attach(ctx)?;
|
||||
// Setup the notification channel
|
||||
opt.sender = self.send.clone();
|
||||
// Setup the auth options
|
||||
opt.auth = sess.au.clone();
|
||||
// Set current NS and DB
|
||||
opt.ns = sess.ns();
|
||||
opt.db = sess.db();
|
||||
// Set strict config
|
||||
opt.strict = strict;
|
||||
// Compute the value
|
||||
let res = val.compute(&ctx, &opt).await?;
|
||||
// Store any data
|
||||
|
@ -459,17 +481,19 @@ impl Datastore {
|
|||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> Result<(), Error> {
|
||||
/// let ds = Datastore::new("memory").await?;
|
||||
/// let ds = Datastore::new("memory").await?.with_notifications();
|
||||
/// let ses = Session::for_kv();
|
||||
/// while let Ok(v) = ds.notifications().recv().await {
|
||||
/// println!("Received notification: {v}");
|
||||
/// }
|
||||
/// if let Some(channel) = ds.notifications() {
|
||||
/// while let Ok(v) = channel.recv().await {
|
||||
/// println!("Received notification: {v}");
|
||||
/// }
|
||||
/// }
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[instrument(skip_all)]
|
||||
pub fn notifications(&self) -> Receiver<Notification> {
|
||||
self.recv.clone()
|
||||
pub fn notifications(&self) -> Option<Receiver<Notification>> {
|
||||
self.notification_channel.as_ref().map(|v| v.1.clone())
|
||||
}
|
||||
|
||||
/// Performs a full database export as SQL
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::sql::paths::EDGE;
|
|||
use crate::sql::paths::IN;
|
||||
use crate::sql::paths::OUT;
|
||||
use crate::sql::thing::Thing;
|
||||
use crate::sql::{Uuid, Value};
|
||||
use crate::sql::value::Value;
|
||||
use channel::Sender;
|
||||
use sql::permission::Permissions;
|
||||
use sql::statements::DefineAnalyzerStatement;
|
||||
|
@ -34,6 +34,7 @@ use std::fmt::Debug;
|
|||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// A set of undoable updates and requests against a dataset.
|
||||
#[allow(dead_code)]
|
||||
|
@ -793,14 +794,14 @@ impl Transaction {
|
|||
// NOTE: Setting cluster membership sets the heartbeat
|
||||
// Remember to set the heartbeat as well
|
||||
pub async fn set_cl(&mut self, id: Uuid) -> Result<(), Error> {
|
||||
let key = crate::key::cl::Cl::new(id.0);
|
||||
match self.get_cl(id.clone()).await? {
|
||||
let key = crate::key::cl::Cl::new(id);
|
||||
match self.get_cl(id).await? {
|
||||
Some(_) => Err(Error::ClAlreadyExists {
|
||||
value: id.0.to_string(),
|
||||
value: id.to_string(),
|
||||
}),
|
||||
None => {
|
||||
let value = ClusterMembership {
|
||||
name: id.0.to_string(),
|
||||
name: id.to_string(),
|
||||
heartbeat: self.clock(),
|
||||
};
|
||||
self.put(key, value).await?;
|
||||
|
@ -811,7 +812,7 @@ impl Transaction {
|
|||
|
||||
// Retrieve cluster information
|
||||
pub async fn get_cl(&mut self, id: Uuid) -> Result<Option<ClusterMembership>, Error> {
|
||||
let key = crate::key::cl::Cl::new(id.0);
|
||||
let key = crate::key::cl::Cl::new(id);
|
||||
let val = self.get(key).await?;
|
||||
match val {
|
||||
Some(v) => Ok(Some::<ClusterMembership>(v.into())),
|
||||
|
@ -830,12 +831,12 @@ impl Transaction {
|
|||
// Set heartbeat
|
||||
pub async fn set_hb(&mut self, id: Uuid) -> Result<(), Error> {
|
||||
let now = self.clock();
|
||||
let key = crate::key::hb::Hb::new(now.clone(), id.0);
|
||||
let key = crate::key::hb::Hb::new(now.clone(), id);
|
||||
// We do not need to do a read, we always want to overwrite
|
||||
self.put(
|
||||
key,
|
||||
ClusterMembership {
|
||||
name: id.0.to_string(),
|
||||
name: id.to_string(),
|
||||
heartbeat: now,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -78,7 +78,7 @@ impl Fields {
|
|||
group: bool,
|
||||
) -> Result<Value, Error> {
|
||||
// Ensure futures are run
|
||||
let opt = &opt.futures(true);
|
||||
let opt = &opt.new_with_futures(true);
|
||||
//
|
||||
let doc = ctx.doc().unwrap_or(&Value::None);
|
||||
let mut ctx = Context::new(ctx);
|
||||
|
|
|
@ -135,7 +135,7 @@ impl Function {
|
|||
// Prevent long function chains
|
||||
let opt = &opt.dive(1)?;
|
||||
// Ensure futures are run
|
||||
let opt = &opt.futures(true);
|
||||
let opt = &opt.new_with_futures(true);
|
||||
// Process the function type
|
||||
match self {
|
||||
Self::Normal(s, x) => {
|
||||
|
|
|
@ -50,7 +50,7 @@ impl CreateStatement {
|
|||
// Create a new iterator
|
||||
let mut i = Iterator::new();
|
||||
// Ensure futures are stored
|
||||
let opt = &opt.futures(false);
|
||||
let opt = &opt.new_with_futures(false);
|
||||
// Loop over the create targets
|
||||
for w in self.what.0.iter() {
|
||||
let v = w.compute(ctx, opt).await?;
|
||||
|
|
|
@ -838,13 +838,13 @@ impl DefineTableStatement {
|
|||
// Release the transaction
|
||||
drop(run);
|
||||
// Force queries to run
|
||||
let opt = &opt.force(true);
|
||||
let opt = &opt.new_with_force(true);
|
||||
// Don't process field queries
|
||||
let opt = &opt.fields(false);
|
||||
let opt = &opt.new_with_fields(false);
|
||||
// Don't process event queries
|
||||
let opt = &opt.events(false);
|
||||
let opt = &opt.new_with_events(false);
|
||||
// Don't process index queries
|
||||
let opt = &opt.indexes(false);
|
||||
let opt = &opt.new_with_indexes(false);
|
||||
// Process each foreign table
|
||||
for v in view.what.0.iter() {
|
||||
// Process the view data
|
||||
|
@ -1267,13 +1267,13 @@ impl DefineIndexStatement {
|
|||
// Release the transaction
|
||||
drop(run);
|
||||
// Force queries to run
|
||||
let opt = &opt.force(true);
|
||||
let opt = &opt.new_with_force(true);
|
||||
// Don't process field queries
|
||||
let opt = &opt.fields(false);
|
||||
let opt = &opt.new_with_fields(false);
|
||||
// Don't process event queries
|
||||
let opt = &opt.events(false);
|
||||
let opt = &opt.new_with_events(false);
|
||||
// Don't process table queries
|
||||
let opt = &opt.tables(false);
|
||||
let opt = &opt.new_with_tables(false);
|
||||
// Update the index data
|
||||
let stm = UpdateStatement {
|
||||
what: Values(vec![Value::Table(self.what.clone().into())]),
|
||||
|
|
|
@ -50,7 +50,7 @@ impl DeleteStatement {
|
|||
// Create a new iterator
|
||||
let mut i = Iterator::new();
|
||||
// Ensure futures are stored
|
||||
let opt = &opt.futures(false);
|
||||
let opt = &opt.new_with_futures(false);
|
||||
// Loop over the delete targets
|
||||
for w in self.what.0.iter() {
|
||||
let v = w.compute(ctx, opt).await?;
|
||||
|
|
|
@ -53,7 +53,7 @@ impl InsertStatement {
|
|||
// Create a new iterator
|
||||
let mut i = Iterator::new();
|
||||
// Ensure futures are stored
|
||||
let opt = &opt.futures(false);
|
||||
let opt = &opt.new_with_futures(false);
|
||||
// Parse the expression
|
||||
match &self.data {
|
||||
// Check if this is a traditional statement
|
||||
|
|
|
@ -30,16 +30,16 @@ impl KillStatement {
|
|||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Fetch the live query key
|
||||
let key = crate::key::lq::new(opt.id(), opt.ns(), opt.db(), &self.id);
|
||||
let key = crate::key::lq::new(opt.id()?, opt.ns(), opt.db(), self.id.0);
|
||||
// Fetch the live query key if it exists
|
||||
match run.get(key).await? {
|
||||
Some(val) => match std::str::from_utf8(&val) {
|
||||
Ok(tb) => {
|
||||
// Delete the node live query
|
||||
let key = crate::key::lq::new(opt.id(), opt.ns(), opt.db(), &self.id);
|
||||
let key = crate::key::lq::new(opt.id()?, opt.ns(), opt.db(), self.id.0);
|
||||
run.del(key).await?;
|
||||
// Delete the table live query
|
||||
let key = crate::key::lv::new(opt.ns(), opt.db(), tb, &self.id);
|
||||
let key = crate::key::lv::new(opt.ns(), opt.db(), tb, self.id.0);
|
||||
run.del(key).await?;
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -49,12 +49,12 @@ impl LiveStatement {
|
|||
// Clone the current statement
|
||||
let mut stm = self.clone();
|
||||
// Store the current Node ID
|
||||
stm.node = Uuid(*opt.id);
|
||||
stm.node = Uuid(opt.id()?);
|
||||
// Insert the node live query
|
||||
let key = crate::key::lq::new(opt.id(), opt.ns(), opt.db(), &self.id);
|
||||
let key = crate::key::lq::new(opt.id()?, opt.ns(), opt.db(), self.id.0);
|
||||
run.putc(key, tb.as_str(), None).await?;
|
||||
// Insert the table live query
|
||||
let key = crate::key::lv::new(opt.ns(), opt.db(), &tb, &self.id);
|
||||
let key = crate::key::lv::new(opt.ns(), opt.db(), &tb, self.id.0);
|
||||
run.putc(key, stm, None).await?;
|
||||
}
|
||||
v => {
|
||||
|
@ -64,7 +64,7 @@ impl LiveStatement {
|
|||
}
|
||||
};
|
||||
// Return the query id
|
||||
Ok(Value::Uuid(self.id.clone()))
|
||||
Ok(self.id.clone().into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ impl OutputStatement {
|
|||
/// Process this type returning a computed simple Value
|
||||
pub(crate) async fn compute(&self, ctx: &Context<'_>, opt: &Options) -> Result<Value, Error> {
|
||||
// Ensure futures are processed
|
||||
let opt = &opt.futures(true);
|
||||
let opt = &opt.new_with_futures(true);
|
||||
// Process the output value
|
||||
let mut val = self.what.compute(ctx, opt).await?;
|
||||
// Fetch any
|
||||
|
|
|
@ -63,7 +63,7 @@ impl RelateStatement {
|
|||
// Create a new iterator
|
||||
let mut i = Iterator::new();
|
||||
// Ensure futures are stored
|
||||
let opt = &opt.futures(false);
|
||||
let opt = &opt.new_with_futures(false);
|
||||
// Loop over the from targets
|
||||
let from = {
|
||||
let mut out = Vec::new();
|
||||
|
|
|
@ -80,7 +80,7 @@ impl SelectStatement {
|
|||
// Create a new iterator
|
||||
let mut i = Iterator::new();
|
||||
// Ensure futures are stored
|
||||
let opt = &opt.futures(false);
|
||||
let opt = &opt.new_with_futures(false);
|
||||
|
||||
// Get a query planner
|
||||
let mut planner = QueryPlanner::new(opt, &self.cond);
|
||||
|
|
|
@ -63,7 +63,6 @@ mod tests {
|
|||
use crate::dbs::Auth;
|
||||
use std::sync::Arc;
|
||||
use std::time::SystemTime;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[test]
|
||||
fn test_sleep_statement_sec() {
|
||||
|
@ -87,8 +86,7 @@ mod tests {
|
|||
async fn test_sleep_compute() {
|
||||
let sql = "SLEEP 500ms";
|
||||
let time = SystemTime::now();
|
||||
let opt =
|
||||
Options::new(Arc::new(Uuid::new_v4()), channel::unbounded().0, Arc::new(Auth::Kv));
|
||||
let opt = Options::default().with_auth(Arc::new(Auth::Kv));
|
||||
let (ctx, _) = mock().await;
|
||||
let (_, stm) = sleep(sql).unwrap();
|
||||
let value = stm.compute(&ctx, &opt).await.unwrap();
|
||||
|
|
|
@ -51,7 +51,7 @@ impl UpdateStatement {
|
|||
// Create a new iterator
|
||||
let mut i = Iterator::new();
|
||||
// Ensure futures are stored
|
||||
let opt = &opt.futures(false);
|
||||
let opt = &opt.new_with_futures(false);
|
||||
// Loop over the update targets
|
||||
for w in self.what.0.iter() {
|
||||
let v = w.compute(ctx, opt).await?;
|
||||
|
|
|
@ -43,7 +43,6 @@ impl Value {
|
|||
// otherwise return none
|
||||
_ => Ok(Value::None),
|
||||
},
|
||||
|
||||
// Current path part is a future
|
||||
Value::Future(v) => {
|
||||
// Check how many path parts are remaining
|
||||
|
@ -53,7 +52,7 @@ impl Value {
|
|||
// Process the future and fetch the embedded field
|
||||
_ => {
|
||||
// Ensure the future is processed
|
||||
let fut = &opt.futures(true);
|
||||
let fut = &opt.new_with_futures(true);
|
||||
// Get the future return value
|
||||
let val = v.compute(ctx, fut).await?;
|
||||
// Fetch the embedded field
|
||||
|
|
|
@ -17,7 +17,7 @@ async fn clear_transaction_cache_table() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -73,7 +73,7 @@ async fn clear_transaction_cache_field() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
|
|
@ -19,7 +19,7 @@ async fn compare_empty() -> Result<(), Error> {
|
|||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -203,7 +203,7 @@ async fn run_queries(
|
|||
> {
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
dbs.execute(sql, &ses, None, false).await.map(|v| v.into_iter().map(|res| res.result))
|
||||
dbs.execute(sql, &ses, None).await.map(|v| v.into_iter().map(|res| res.result))
|
||||
}
|
||||
|
||||
fn with_enough_stack(
|
||||
|
|
|
@ -18,7 +18,7 @@ async fn create_with_id() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -14,7 +14,7 @@ async fn datetimes_conversion() -> Result<(), Error> {
|
|||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -14,7 +14,7 @@ async fn define_statement_namespace() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -39,7 +39,7 @@ async fn define_statement_database() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -68,7 +68,7 @@ async fn define_statement_function() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -101,7 +101,7 @@ async fn define_statement_table_drop() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -132,7 +132,7 @@ async fn define_statement_table_schemaless() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -164,7 +164,7 @@ async fn define_statement_table_schemafull() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -198,7 +198,7 @@ async fn define_statement_table_schemaful() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -238,7 +238,7 @@ async fn define_statement_event() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -295,7 +295,7 @@ async fn define_statement_event_when_event() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -352,7 +352,7 @@ async fn define_statement_event_when_logic() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -401,7 +401,7 @@ async fn define_statement_field() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -433,7 +433,7 @@ async fn define_statement_field_type() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -465,7 +465,7 @@ async fn define_statement_field_value() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -497,7 +497,7 @@ async fn define_statement_field_assert() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -529,7 +529,7 @@ async fn define_statement_field_type_value_assert() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -565,7 +565,7 @@ async fn define_statement_index_single_simple() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -613,7 +613,7 @@ async fn define_statement_index_single() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -657,7 +657,7 @@ async fn define_statement_index_multiple() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -709,7 +709,7 @@ async fn define_statement_index_single_unique() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -767,7 +767,7 @@ async fn define_statement_index_multiple_unique() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 12);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -842,7 +842,7 @@ async fn define_statement_index_single_unique_existing() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
//
|
||||
for _ in 0..3 {
|
||||
|
@ -889,7 +889,7 @@ async fn define_statement_index_multiple_unique_existing() -> Result<(), Error>
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
for _ in 0..4 {
|
||||
|
@ -932,7 +932,7 @@ async fn define_statement_analyzer() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -976,7 +976,7 @@ async fn define_statement_search_index() -> Result<(), Error> {
|
|||
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 8);
|
||||
//
|
||||
for i in 0..6 {
|
||||
|
|
|
@ -18,7 +18,7 @@ async fn complex_ids() -> Result<(), Error> {
|
|||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -96,7 +96,7 @@ async fn complex_strings() -> Result<(), Error> {
|
|||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -23,7 +23,7 @@ async fn create_relate_select() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 12);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -20,7 +20,7 @@ async fn field_definition_value_assert_failure() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -103,7 +103,7 @@ async fn field_definition_value_assert_success() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -152,7 +152,7 @@ async fn field_definition_empty_nested_objects() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -206,7 +206,7 @@ async fn field_definition_empty_nested_arrays() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -258,7 +258,7 @@ async fn field_definition_empty_nested_flexible() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,7 @@ async fn future_function_simple() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -46,7 +46,7 @@ async fn future_function_arguments() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -93,7 +93,7 @@ async fn concurrency() -> Result<(), Error> {
|
|||
let sql = query(limit, MILLIS);
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = dbs.execute(&sql, &ses, None, false).await;
|
||||
let res = dbs.execute(&sql, &ses, None).await;
|
||||
|
||||
if matches!(res, Err(Error::QueryTimedout)) {
|
||||
Ok(false)
|
||||
|
|
|
@ -13,7 +13,7 @@ async fn geometry_point() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -70,7 +70,7 @@ async fn geometry_polygon() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -163,7 +163,7 @@ async fn geometry_multipoint() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -241,7 +241,7 @@ async fn geometry_multipolygon() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -346,7 +346,7 @@ async fn geometry_inner_access() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -22,7 +22,7 @@ async fn select_limit_fetch() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 11);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -246,7 +246,7 @@ async fn select_multi_aggregate() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -351,7 +351,7 @@ async fn select_multi_aggregate_composed() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -16,7 +16,7 @@ async fn insert_statement_object_single() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -44,7 +44,7 @@ async fn insert_statement_object_multiple() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -66,7 +66,7 @@ async fn insert_statement_values_single() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -83,7 +83,7 @@ async fn insert_statement_values_multiple() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -105,7 +105,7 @@ async fn insert_statement_values_retable_id() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -128,7 +128,7 @@ async fn insert_statement_on_duplicate_key() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -149,7 +149,7 @@ async fn insert_statement_output() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -17,7 +17,7 @@ async fn select_limit_fetch() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -15,7 +15,7 @@ async fn select_where_matches_using_index() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let _ = res.remove(0).result?;
|
||||
|
@ -61,7 +61,7 @@ async fn select_where_matches_without_using_index_iterator() -> Result<(), Error
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let _ = res.remove(0).result?;
|
||||
|
@ -102,7 +102,7 @@ async fn select_where_matches_using_index_and_arrays() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let _ = res.remove(0).result?;
|
||||
|
@ -152,7 +152,7 @@ async fn select_where_matches_using_index_offsets() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
for _ in 0..4 {
|
||||
|
@ -164,7 +164,7 @@ async fn select_where_matches_using_index_offsets() -> Result<(), Error> {
|
|||
{
|
||||
id: blog:1,
|
||||
title: {
|
||||
0: [{s:5, e:10}],
|
||||
0: [{s:5, e:10}],
|
||||
},
|
||||
content: {
|
||||
0: [{s:0, e:5}],
|
||||
|
@ -206,7 +206,7 @@ async fn select_where_matches_using_index_and_score() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
for _ in 0..6 {
|
||||
|
@ -240,7 +240,7 @@ async fn select_where_matches_without_using_index_and_score() -> Result<(), Erro
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
//
|
||||
for _ in 0..7 {
|
||||
|
|
|
@ -19,7 +19,7 @@ async fn merge_record() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -13,7 +13,7 @@ async fn model_count() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -38,7 +38,7 @@ async fn model_range() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
|
|
@ -16,7 +16,7 @@ async fn define_global_param() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -59,7 +59,7 @@ async fn define_protected_param() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
|
|
@ -14,7 +14,7 @@ async fn relate_with_parameters() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -51,7 +51,7 @@ async fn relate_and_overwrite() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -15,7 +15,7 @@ async fn remove_statement_table() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -49,7 +49,7 @@ async fn remove_statement_analyzer() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
// Analyzer is defined
|
||||
let tmp = res.remove(0).result;
|
||||
|
|
|
@ -19,7 +19,7 @@ async fn script_function_error() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -46,7 +46,7 @@ async fn script_function_simple() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -75,7 +75,7 @@ async fn script_function_context() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -109,7 +109,7 @@ async fn script_function_arguments() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -152,7 +152,7 @@ async fn script_function_types() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -182,7 +182,7 @@ async fn script_function_module_os() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
|
|
@ -15,7 +15,7 @@ async fn select_field_value() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -75,7 +75,7 @@ async fn select_expression_value() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -135,7 +135,7 @@ async fn select_writeable_subqueries() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -179,7 +179,7 @@ async fn select_where_field_is_bool() -> Result<(), Error> {
|
|||
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -267,7 +267,7 @@ async fn select_where_and_with_index() -> Result<(), Error> {
|
|||
SELECT name FROM person WHERE name = 'Tobie' AND genre = 'm' EXPLAIN;";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let _ = res.remove(0).result?;
|
||||
|
@ -311,7 +311,7 @@ async fn select_where_and_with_unique_index() -> Result<(), Error> {
|
|||
SELECT name FROM person WHERE name = 'Jaime' AND genre = 'm' EXPLAIN;";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
let _ = res.remove(0).result?;
|
||||
|
@ -356,7 +356,7 @@ async fn select_where_and_with_fulltext_index() -> Result<(), Error> {
|
|||
SELECT name FROM person WHERE name @@ 'Jaime' AND genre = 'm' EXPLAIN;";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let _ = res.remove(0).result?;
|
||||
|
|
|
@ -15,9 +15,9 @@ async fn strict_mode_no_namespace() -> Result<(), Error> {
|
|||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = Datastore::new("memory").await?.with_strict_mode(true);
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, true).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -73,9 +73,9 @@ async fn strict_mode_no_database() -> Result<(), Error> {
|
|||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = Datastore::new("memory").await?.with_strict_mode(true);
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, true).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -126,9 +126,9 @@ async fn strict_mode_no_table() -> Result<(), Error> {
|
|||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = Datastore::new("memory").await?.with_strict_mode(true);
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, true).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -174,9 +174,9 @@ async fn strict_mode_all_ok() -> Result<(), Error> {
|
|||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = Datastore::new("memory").await?.with_strict_mode(true);
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, true).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -215,7 +215,7 @@ async fn loose_mode_all_ok() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
|
|
@ -25,7 +25,7 @@ async fn subquery_select() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -137,7 +137,7 @@ async fn subquery_ifelse_set() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -252,7 +252,7 @@ async fn subquery_ifelse_array() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -28,7 +28,7 @@ async fn define_foreign_table() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
|
|
@ -20,7 +20,7 @@ async fn strict_typing_inline() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -136,7 +136,7 @@ async fn strict_typing_defined() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 8);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
|
|
@ -31,7 +31,7 @@ async fn update_simple_with_input() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
@ -111,7 +111,7 @@ async fn update_complex_with_input() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
|
|
|
@ -14,7 +14,7 @@ async fn use_statement_set_ns() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -40,7 +40,7 @@ async fn use_statement_set_db() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -66,7 +66,7 @@ async fn use_statement_set_both() -> Result<(), Error> {
|
|||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None, false).await?;
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -9,7 +9,6 @@ pub static CF: OnceCell<Config> = OnceCell::new();
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Config {
|
||||
pub strict: bool,
|
||||
pub bind: SocketAddr,
|
||||
pub path: String,
|
||||
#[cfg(feature = "has-storage")]
|
||||
|
|
|
@ -50,10 +50,6 @@ pub struct StartCommandArguments {
|
|||
kvs: Option<StartCommandRemoteTlsOptions>,
|
||||
#[command(flatten)]
|
||||
web: Option<StartCommandWebTlsOptions>,
|
||||
#[arg(help = "Whether strict mode is enabled on this database instance")]
|
||||
#[arg(env = "SURREAL_STRICT", short = 's', long = "strict")]
|
||||
#[arg(default_value_t = false)]
|
||||
strict: bool,
|
||||
#[arg(help = "The logging level for the database server")]
|
||||
#[arg(env = "SURREAL_LOG", short = 'l', long = "log")]
|
||||
#[arg(default_value = "info")]
|
||||
|
@ -99,7 +95,6 @@ pub async fn init(
|
|||
listen_addresses,
|
||||
dbs,
|
||||
web,
|
||||
strict,
|
||||
log: CustomEnvFilter(log),
|
||||
no_banner,
|
||||
..
|
||||
|
@ -115,7 +110,6 @@ pub async fn init(
|
|||
}
|
||||
// Setup the cli options
|
||||
let _ = config::CF.set(Config {
|
||||
strict,
|
||||
bind: listen_addresses.first().cloned().unwrap(),
|
||||
client_ip,
|
||||
path,
|
||||
|
|
|
@ -1,35 +1,54 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::cli::CF;
|
||||
use crate::err::Error;
|
||||
use clap::Args;
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::time::Duration;
|
||||
use surrealdb::kvs::Datastore;
|
||||
|
||||
pub static DB: OnceCell<Datastore> = OnceCell::new();
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct StartCommandDbsOptions {
|
||||
#[arg(help = "The maximum duration of any query")]
|
||||
#[arg(help = "Whether strict mode is enabled on this database instance")]
|
||||
#[arg(env = "SURREAL_STRICT", short = 's', long = "strict")]
|
||||
#[arg(default_value_t = false)]
|
||||
strict_mode: bool,
|
||||
#[arg(help = "The maximum duration that a set of statements can run for")]
|
||||
#[arg(env = "SURREAL_QUERY_TIMEOUT", long)]
|
||||
#[arg(value_parser = super::cli::validator::duration)]
|
||||
query_timeout: Option<Duration>,
|
||||
#[arg(help = "The maximum duration that any single transaction can run for")]
|
||||
#[arg(env = "SURREAL_TRANSACTION_TIMEOUT", long)]
|
||||
#[arg(value_parser = super::cli::validator::duration)]
|
||||
transaction_timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
pub async fn init(
|
||||
StartCommandDbsOptions {
|
||||
strict_mode,
|
||||
query_timeout,
|
||||
transaction_timeout,
|
||||
}: StartCommandDbsOptions,
|
||||
) -> Result<(), Error> {
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Log authentication options
|
||||
match opt.strict {
|
||||
true => info!("Database strict mode is enabled"),
|
||||
false => info!("Database strict mode is disabled"),
|
||||
};
|
||||
// Log specified strict mode
|
||||
debug!("Database strict mode is {strict_mode}");
|
||||
// Log specified query timeout
|
||||
if let Some(v) = query_timeout {
|
||||
debug!("Maximum query processing timeout is {v:?}");
|
||||
}
|
||||
// Log specified parse timeout
|
||||
if let Some(v) = transaction_timeout {
|
||||
debug!("Maximum transaction processing timeout is {v:?}");
|
||||
}
|
||||
// Parse and setup the desired kv datastore
|
||||
let dbs = Datastore::new(&opt.path).await?.query_timeout(query_timeout);
|
||||
let dbs = Datastore::new(&opt.path)
|
||||
.await?
|
||||
.with_notifications()
|
||||
.with_strict_mode(strict_mode)
|
||||
.with_query_timeout(query_timeout)
|
||||
.with_transaction_timeout(transaction_timeout);
|
||||
// Store database instance
|
||||
let _ = DB.set(dbs);
|
||||
// All ok
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::cli::CF;
|
||||
use crate::dbs::DB;
|
||||
use crate::err::Error;
|
||||
use crate::net::input::bytes_to_utf8;
|
||||
|
@ -33,12 +32,10 @@ async fn handler(
|
|||
true => {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Convert the body to a byte slice
|
||||
let sql = bytes_to_utf8(&sql)?;
|
||||
// Execute the sql query in the database
|
||||
match db.execute(sql, &session, None, opt.strict).await {
|
||||
match db.execute(sql, &session, None).await {
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::cli::CF;
|
||||
use crate::dbs::DB;
|
||||
use crate::err::Error;
|
||||
use crate::net::input::bytes_to_utf8;
|
||||
|
@ -156,8 +155,6 @@ async fn select_all(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the request statement
|
||||
let sql = format!(
|
||||
"SELECT * FROM type::table($table) LIMIT {l} START {s}",
|
||||
|
@ -169,7 +166,7 @@ async fn select_all(
|
|||
String::from("table") => Value::from(table),
|
||||
};
|
||||
// Execute the query and return the result
|
||||
match db.execute(sql.as_str(), &session, Some(vars), opt.strict).await {
|
||||
match db.execute(sql.as_str(), &session, Some(vars)).await {
|
||||
Ok(ref res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
@ -194,8 +191,6 @@ async fn create_all(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Convert the HTTP request body
|
||||
let data = bytes_to_utf8(&body)?;
|
||||
// Parse the request body as JSON
|
||||
|
@ -210,7 +205,7 @@ async fn create_all(
|
|||
=> params.parse()
|
||||
};
|
||||
// Execute the query and return the result
|
||||
match db.execute(sql, &session, Some(vars), opt.strict).await {
|
||||
match db.execute(sql, &session, Some(vars)).await {
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
@ -238,8 +233,6 @@ async fn update_all(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Convert the HTTP request body
|
||||
let data = bytes_to_utf8(&body)?;
|
||||
// Parse the request body as JSON
|
||||
|
@ -254,7 +247,7 @@ async fn update_all(
|
|||
=> params.parse()
|
||||
};
|
||||
// Execute the query and return the result
|
||||
match db.execute(sql, &session, Some(vars), opt.strict).await {
|
||||
match db.execute(sql, &session, Some(vars)).await {
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
@ -282,8 +275,6 @@ async fn modify_all(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Convert the HTTP request body
|
||||
let data = bytes_to_utf8(&body)?;
|
||||
// Parse the request body as JSON
|
||||
|
@ -298,7 +289,7 @@ async fn modify_all(
|
|||
=> params.parse()
|
||||
};
|
||||
// Execute the query and return the result
|
||||
match db.execute(sql, &session, Some(vars), opt.strict).await {
|
||||
match db.execute(sql, &session, Some(vars)).await {
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
@ -325,8 +316,6 @@ async fn delete_all(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the request statement
|
||||
let sql = "DELETE type::table($table) RETURN BEFORE";
|
||||
// Specify the request variables
|
||||
|
@ -335,7 +324,7 @@ async fn delete_all(
|
|||
=> params.parse()
|
||||
};
|
||||
// Execute the query and return the result
|
||||
match db.execute(sql, &session, Some(vars), opt.strict).await {
|
||||
match db.execute(sql, &session, Some(vars)).await {
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
@ -363,8 +352,6 @@ async fn select_one(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the request statement
|
||||
let sql = "SELECT * FROM type::thing($table, $id)";
|
||||
// Parse the Record ID as a SurrealQL value
|
||||
|
@ -378,7 +365,7 @@ async fn select_one(
|
|||
String::from("id") => rid,
|
||||
};
|
||||
// Execute the query and return the result
|
||||
match db.execute(sql, &session, Some(vars), opt.strict).await {
|
||||
match db.execute(sql, &session, Some(vars)).await {
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
@ -404,8 +391,6 @@ async fn create_one(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Convert the HTTP request body
|
||||
let data = bytes_to_utf8(&body)?;
|
||||
// Parse the Record ID as a SurrealQL value
|
||||
|
@ -426,7 +411,7 @@ async fn create_one(
|
|||
=> params.parse()
|
||||
};
|
||||
// Execute the query and return the result
|
||||
match db.execute(sql, &session, Some(vars), opt.strict).await {
|
||||
match db.execute(sql, &session, Some(vars)).await {
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
@ -455,8 +440,6 @@ async fn update_one(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Convert the HTTP request body
|
||||
let data = bytes_to_utf8(&body)?;
|
||||
// Parse the Record ID as a SurrealQL value
|
||||
|
@ -477,7 +460,7 @@ async fn update_one(
|
|||
=> params.parse()
|
||||
};
|
||||
// Execute the query and return the result
|
||||
match db.execute(sql, &session, Some(vars), opt.strict).await {
|
||||
match db.execute(sql, &session, Some(vars)).await {
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
@ -506,8 +489,6 @@ async fn modify_one(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Convert the HTTP request body
|
||||
let data = bytes_to_utf8(&body)?;
|
||||
// Parse the Record ID as a SurrealQL value
|
||||
|
@ -528,7 +509,7 @@ async fn modify_one(
|
|||
=> params.parse()
|
||||
};
|
||||
// Execute the query and return the result
|
||||
match db.execute(sql, &session, Some(vars), opt.strict).await {
|
||||
match db.execute(sql, &session, Some(vars)).await {
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
@ -556,8 +537,6 @@ async fn delete_one(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get the datastore reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the request statement
|
||||
let sql = "DELETE type::thing($table, $id) RETURN BEFORE";
|
||||
// Parse the Record ID as a SurrealQL value
|
||||
|
@ -572,7 +551,7 @@ async fn delete_one(
|
|||
=> params.parse()
|
||||
};
|
||||
// Execute the query and return the result
|
||||
match db.execute(sql, &session, Some(vars), opt.strict).await {
|
||||
match db.execute(sql, &session, Some(vars)).await {
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
"application/json" => Ok(output::json(&output::simplify(res))),
|
||||
|
|
|
@ -13,7 +13,6 @@ use crate::rpc::res::Failure;
|
|||
use crate::rpc::res::Output;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
@ -125,35 +124,37 @@ impl Rpc {
|
|||
let moved_rpc = rpc.clone();
|
||||
tokio::task::spawn(async move {
|
||||
let rpc = moved_rpc;
|
||||
while let Ok(v) = DB.get().unwrap().notifications().recv().await {
|
||||
trace!("Received notification: {:?}", v);
|
||||
// Find which websocket the notification belongs to
|
||||
match LIVE_QUERIES.read().await.get(&v.id) {
|
||||
Some(ws_id) => {
|
||||
// Send the notification to the client
|
||||
let msg_text = res::success(None, v.clone());
|
||||
let ws_write = WEBSOCKETS.write().await;
|
||||
match ws_write.get(ws_id) {
|
||||
None => {
|
||||
error!(
|
||||
"Tracked WebSocket {:?} not found for lq: {:?}",
|
||||
ws_id, &v.id
|
||||
);
|
||||
}
|
||||
Some(ws_sender) => {
|
||||
msg_text
|
||||
.send(rpc.read().await.format.clone(), ws_sender.clone())
|
||||
.await;
|
||||
trace!(
|
||||
"Sent notification to WebSocket {:?} for lq: {:?}",
|
||||
ws_id,
|
||||
&v.id
|
||||
);
|
||||
if let Some(channel) = DB.get().unwrap().notifications() {
|
||||
while let Ok(v) = channel.recv().await {
|
||||
trace!("Received notification: {:?}", v);
|
||||
// Find which websocket the notification belongs to
|
||||
match LIVE_QUERIES.read().await.get(&v.id) {
|
||||
Some(ws_id) => {
|
||||
// Send the notification to the client
|
||||
let msg_text = res::success(None, v.clone());
|
||||
let ws_write = WEBSOCKETS.write().await;
|
||||
match ws_write.get(ws_id) {
|
||||
None => {
|
||||
error!(
|
||||
"Tracked WebSocket {:?} not found for lq: {:?}",
|
||||
ws_id, &v.id
|
||||
);
|
||||
}
|
||||
Some(ws_sender) => {
|
||||
msg_text
|
||||
.send(rpc.read().await.format.clone(), ws_sender.clone())
|
||||
.await;
|
||||
trace!(
|
||||
"Sent notification to WebSocket {:?} for lq: {:?}",
|
||||
ws_id,
|
||||
&v.id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
error!("Unknown websocket for live query: {:?}", v.id);
|
||||
None => {
|
||||
error!("Unknown websocket for live query: {:?}", v.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -434,8 +435,7 @@ impl Rpc {
|
|||
#[instrument(skip_all, name = "rpc signup", fields(websocket=self.uuid.to_string()))]
|
||||
async fn signup(&mut self, vars: Object) -> Result<Value, Error> {
|
||||
let kvs = DB.get().unwrap();
|
||||
let opts = CF.get().unwrap();
|
||||
surrealdb::iam::signup::signup(kvs, opts.strict, &mut self.session, vars)
|
||||
surrealdb::iam::signup::signup(kvs, &mut self.session, vars)
|
||||
.await
|
||||
.map(Into::into)
|
||||
.map_err(Into::into)
|
||||
|
@ -449,7 +449,7 @@ impl Rpc {
|
|||
username: &opts.user,
|
||||
password: pass,
|
||||
});
|
||||
surrealdb::iam::signin::signin(kvs, &root, opts.strict, &mut self.session, vars)
|
||||
surrealdb::iam::signin::signin(kvs, &root, &mut self.session, vars)
|
||||
.await
|
||||
.map(Into::into)
|
||||
.map_err(Into::into)
|
||||
|
@ -475,12 +475,10 @@ impl Rpc {
|
|||
async fn info(&self) -> Result<Value, Error> {
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the SQL query string
|
||||
let sql = "SELECT * FROM $auth";
|
||||
// Execute the query on the database
|
||||
let mut res = kvs.execute(sql, &self.session, None, opt.strict).await?;
|
||||
let mut res = kvs.execute(sql, &self.session, None).await?;
|
||||
// Extract the first value from the result
|
||||
let res = res.remove(0).result?.first();
|
||||
// Return the result to the client
|
||||
|
@ -560,8 +558,6 @@ impl Rpc {
|
|||
let one = what.is_thing();
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the SQL query string
|
||||
let sql = "SELECT * FROM $what";
|
||||
// Specify the query parameters
|
||||
|
@ -570,7 +566,7 @@ impl Rpc {
|
|||
=> &self.vars
|
||||
});
|
||||
// Execute the query on the database
|
||||
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
||||
// Extract the first query result
|
||||
let res = match one {
|
||||
true => res.remove(0).result?.first(),
|
||||
|
@ -590,8 +586,6 @@ impl Rpc {
|
|||
let one = what.is_thing();
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the SQL query string
|
||||
let sql = "CREATE $what CONTENT $data RETURN AFTER";
|
||||
// Specify the query parameters
|
||||
|
@ -601,7 +595,7 @@ impl Rpc {
|
|||
=> &self.vars
|
||||
});
|
||||
// Execute the query on the database
|
||||
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
||||
// Extract the first query result
|
||||
let res = match one {
|
||||
true => res.remove(0).result?.first(),
|
||||
|
@ -621,8 +615,6 @@ impl Rpc {
|
|||
let one = what.is_thing();
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the SQL query string
|
||||
let sql = "UPDATE $what CONTENT $data RETURN AFTER";
|
||||
// Specify the query parameters
|
||||
|
@ -632,7 +624,7 @@ impl Rpc {
|
|||
=> &self.vars
|
||||
});
|
||||
// Execute the query on the database
|
||||
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
||||
// Extract the first query result
|
||||
let res = match one {
|
||||
true => res.remove(0).result?.first(),
|
||||
|
@ -652,8 +644,6 @@ impl Rpc {
|
|||
let one = what.is_thing();
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the SQL query string
|
||||
let sql = "UPDATE $what MERGE $data RETURN AFTER";
|
||||
// Specify the query parameters
|
||||
|
@ -663,7 +653,7 @@ impl Rpc {
|
|||
=> &self.vars
|
||||
});
|
||||
// Execute the query on the database
|
||||
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
||||
// Extract the first query result
|
||||
let res = match one {
|
||||
true => res.remove(0).result?.first(),
|
||||
|
@ -683,8 +673,6 @@ impl Rpc {
|
|||
let one = what.is_thing();
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the SQL query string
|
||||
let sql = "UPDATE $what PATCH $data RETURN DIFF";
|
||||
// Specify the query parameters
|
||||
|
@ -694,7 +682,7 @@ impl Rpc {
|
|||
=> &self.vars
|
||||
});
|
||||
// Execute the query on the database
|
||||
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
||||
// Extract the first query result
|
||||
let res = match one {
|
||||
true => res.remove(0).result?.first(),
|
||||
|
@ -714,8 +702,6 @@ impl Rpc {
|
|||
let one = what.is_thing();
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the SQL query string
|
||||
let sql = "DELETE $what RETURN BEFORE";
|
||||
// Specify the query parameters
|
||||
|
@ -724,7 +710,7 @@ impl Rpc {
|
|||
=> &self.vars
|
||||
});
|
||||
// Execute the query on the database
|
||||
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
||||
// Extract the first query result
|
||||
let res = match one {
|
||||
true => res.remove(0).result?.first(),
|
||||
|
@ -763,12 +749,10 @@ impl Rpc {
|
|||
async fn query(&self, sql: Strand) -> Result<Vec<Response>, Error> {
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the query parameters
|
||||
let var = Some(self.vars.clone());
|
||||
// Execute the query on the database
|
||||
let res = kvs.execute(&sql, &self.session, var, opt.strict).await?;
|
||||
let res = kvs.execute(&sql, &self.session, var).await?;
|
||||
// Post-process hooks for web layer
|
||||
for response in &res {
|
||||
self.handle_live_query_results(response).await;
|
||||
|
@ -781,12 +765,10 @@ impl Rpc {
|
|||
async fn query_with(&self, sql: Strand, mut vars: Object) -> Result<Vec<Response>, Error> {
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Specify the query parameters
|
||||
let var = Some(mrg! { vars.0, &self.vars });
|
||||
// Execute the query on the database
|
||||
let res = kvs.execute(&sql, &self.session, var, opt.strict).await?;
|
||||
let res = kvs.execute(&sql, &self.session, var).await?;
|
||||
// Post-process hooks for web layer
|
||||
for response in &res {
|
||||
self.handle_live_query_results(response).await;
|
||||
|
|
|
@ -67,7 +67,7 @@ async fn handler(
|
|||
username: &opts.user,
|
||||
password: pass,
|
||||
});
|
||||
match surrealdb::iam::signin::signin(kvs, &root, opts.strict, &mut session, vars)
|
||||
match surrealdb::iam::signin::signin(kvs, &root, &mut session, vars)
|
||||
.await
|
||||
.map_err(Error::from)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::err::Error;
|
|||
use crate::net::input::bytes_to_utf8;
|
||||
use crate::net::output;
|
||||
use crate::net::session;
|
||||
use crate::net::CF;
|
||||
use bytes::Bytes;
|
||||
use serde::Serialize;
|
||||
use surrealdb::dbs::Session;
|
||||
|
@ -54,17 +53,13 @@ async fn handler(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get the config options
|
||||
let opts = CF.get().unwrap();
|
||||
// Convert the HTTP body into text
|
||||
let data = bytes_to_utf8(&body)?;
|
||||
// Parse the provided data as JSON
|
||||
match surrealdb::sql::json(data) {
|
||||
// The provided value was an object
|
||||
Ok(Value::Object(vars)) => {
|
||||
match surrealdb::iam::signup::signup(kvs, opts.strict, &mut session, vars)
|
||||
.await
|
||||
.map_err(Error::from)
|
||||
match surrealdb::iam::signup::signup(kvs, &mut session, vars).await.map_err(Error::from)
|
||||
{
|
||||
// Authentication was successful
|
||||
Ok(v) => match output.as_deref() {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::cli::CF;
|
||||
use crate::dbs::DB;
|
||||
use crate::err::Error;
|
||||
use crate::net::input::bytes_to_utf8;
|
||||
|
@ -45,12 +44,10 @@ async fn handler(
|
|||
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Get a database reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Convert the received sql query
|
||||
let sql = bytes_to_utf8(&sql)?;
|
||||
// Execute the received sql query
|
||||
match db.execute(sql, &session, params.parse().into(), opt.strict).await {
|
||||
match db.execute(sql, &session, params.parse().into()).await {
|
||||
// Convert the response to JSON
|
||||
Ok(res) => match output.as_ref() {
|
||||
// Simple serialization
|
||||
|
@ -76,10 +73,8 @@ async fn socket(ws: WebSocket, session: Session) {
|
|||
if let Ok(sql) = msg.to_str() {
|
||||
// Get a database reference
|
||||
let db = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
let opt = CF.get().unwrap();
|
||||
// Execute the received sql query
|
||||
let _ = match db.execute(sql, &session, None, opt.strict).await {
|
||||
let _ = match db.execute(sql, &session, None).await {
|
||||
// Convert the response to JSON
|
||||
Ok(v) => match serde_json::to_string(&v) {
|
||||
// Send the JSON response to the client
|
||||
|
|
Loading…
Reference in a new issue