Improve datastore configuration options ()

This commit is contained in:
Tobie Morgan Hitchcock 2023-07-05 22:26:13 +01:00 committed by GitHub
parent 67687496c6
commit 4b690c763b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
79 changed files with 878 additions and 785 deletions

View file

@ -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();
});
})
});

View file

@ -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`.

View file

@ -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))
}

View file

@ -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;

View file

@ -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;

View file

@ -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> {

View file

@ -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
}

View file

@ -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);

View file

@ -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

View file

@ -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));

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -19,7 +19,7 @@ impl<'a> Document<'a> {
opt: &Options,
_stm: &Statement<'_>,
) -> Result<(), Error> {
// Check events
// Check indexes
if !opt.indexes {
return Ok(());
}

View file

@ -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(())

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -10,6 +10,7 @@ pub struct Cl {
_a: u8,
_b: u8,
_c: u8,
#[serde(with = "uuid::serde::compact")]
pub nd: Uuid,
}

View file

@ -11,6 +11,7 @@ pub struct Hb {
_c: u8,
_d: u8,
pub hb: Timestamp,
#[serde(with = "uuid::serde::compact")]
pub nd: Uuid,
}

View file

@ -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> {

View file

@ -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> {

View file

@ -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

View file

@ -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,
},
)

View file

@ -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);

View file

@ -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) => {

View file

@ -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?;

View file

@ -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())]),

View file

@ -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?;

View file

@ -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

View file

@ -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?;
}
_ => {

View file

@ -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())
}
}

View file

@ -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

View file

@ -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();

View file

@ -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);

View file

@ -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();

View file

@ -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?;

View file

@ -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

View file

@ -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;

View file

@ -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?;

View file

@ -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(

View file

@ -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?;

View file

@ -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?;

View file

@ -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 {

View file

@ -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?;

View file

@ -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?;

View file

@ -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

View file

@ -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)

View file

@ -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?;

View file

@ -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?;

View file

@ -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?;

View file

@ -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?;

View file

@ -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 {

View file

@ -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?;

View file

@ -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;

View file

@ -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;

View file

@ -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?;

View file

@ -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;

View file

@ -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;

View file

@ -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?;

View file

@ -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;

View file

@ -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?;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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?;

View file

@ -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")]

View file

@ -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,

View file

@ -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

View file

@ -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))),

View file

@ -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))),

View file

@ -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;

View file

@ -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)
{

View file

@ -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() {

View file

@ -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