Simplify external API when working with Datastore
This commit is contained in:
parent
6a8c53b51e
commit
ffc3ed82f7
15 changed files with 702 additions and 554 deletions
|
@ -1,55 +0,0 @@
|
||||||
use crate::dbs::Attach;
|
|
||||||
use crate::dbs::Executor;
|
|
||||||
use crate::dbs::Options;
|
|
||||||
use crate::dbs::Response;
|
|
||||||
use crate::dbs::Session;
|
|
||||||
use crate::dbs::Variables;
|
|
||||||
use crate::err::Error;
|
|
||||||
use crate::kvs::Store;
|
|
||||||
use crate::sql;
|
|
||||||
use crate::sql::query::Query;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub async fn execute(
|
|
||||||
kvs: Store,
|
|
||||||
txt: &str,
|
|
||||||
session: Session,
|
|
||||||
vars: Variables,
|
|
||||||
) -> Result<Vec<Response>, Error> {
|
|
||||||
// Create a new query options
|
|
||||||
let mut opt = Options::default();
|
|
||||||
// Create a new query executor
|
|
||||||
let mut exe = Executor::new(kvs);
|
|
||||||
// Create a new execution context
|
|
||||||
let ctx = session.context();
|
|
||||||
// Attach the defined variables
|
|
||||||
let ctx = vars.attach(ctx);
|
|
||||||
// Parse the SQL query text
|
|
||||||
let ast = sql::parse(txt)?;
|
|
||||||
// Process all statements
|
|
||||||
opt.auth = Arc::new(session.au);
|
|
||||||
opt.ns = session.ns.map(Arc::new);
|
|
||||||
opt.db = session.db.map(Arc::new);
|
|
||||||
exe.execute(ctx, opt, ast).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn process(
|
|
||||||
kvs: Store,
|
|
||||||
ast: Query,
|
|
||||||
session: Session,
|
|
||||||
vars: Variables,
|
|
||||||
) -> Result<Vec<Response>, Error> {
|
|
||||||
// Create a new query options
|
|
||||||
let mut opt = Options::default();
|
|
||||||
// Create a new query executor
|
|
||||||
let mut exe = Executor::new(kvs);
|
|
||||||
// Store session info on context
|
|
||||||
let ctx = session.context();
|
|
||||||
// Attach the defined variables
|
|
||||||
let ctx = vars.attach(ctx);
|
|
||||||
// Process all statements
|
|
||||||
opt.auth = Arc::new(session.au);
|
|
||||||
opt.ns = session.ns.map(Arc::new);
|
|
||||||
opt.db = session.db.map(Arc::new);
|
|
||||||
exe.execute(ctx, opt, ast).await
|
|
||||||
}
|
|
|
@ -6,7 +6,7 @@ use crate::dbs::Options;
|
||||||
use crate::dbs::Runtime;
|
use crate::dbs::Runtime;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::kvs::Store;
|
use crate::kvs::Datastore;
|
||||||
use crate::sql::query::Query;
|
use crate::sql::query::Query;
|
||||||
use crate::sql::statement::Statement;
|
use crate::sql::statement::Statement;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
@ -14,14 +14,14 @@ use futures::lock::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use trice::Instant;
|
use trice::Instant;
|
||||||
|
|
||||||
pub struct Executor {
|
pub struct Executor<'a> {
|
||||||
err: bool,
|
err: bool,
|
||||||
kvs: Store,
|
kvs: &'a Datastore,
|
||||||
txn: Option<Transaction>,
|
txn: Option<Transaction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Executor {
|
impl<'a> Executor<'a> {
|
||||||
pub fn new(kvs: Store) -> Executor {
|
pub fn new(kvs: &'a Datastore) -> Executor<'a> {
|
||||||
Executor {
|
Executor {
|
||||||
kvs,
|
kvs,
|
||||||
txn: None,
|
txn: None,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
mod auth;
|
mod auth;
|
||||||
mod dbs;
|
|
||||||
mod executor;
|
mod executor;
|
||||||
mod iterate;
|
mod iterate;
|
||||||
mod iterator;
|
mod iterator;
|
||||||
|
@ -12,7 +11,6 @@ mod transaction;
|
||||||
mod variables;
|
mod variables;
|
||||||
|
|
||||||
pub use self::auth::*;
|
pub use self::auth::*;
|
||||||
pub use self::dbs::*;
|
|
||||||
pub use self::executor::*;
|
pub use self::executor::*;
|
||||||
pub use self::iterator::*;
|
pub use self::iterator::*;
|
||||||
pub use self::options::*;
|
pub use self::options::*;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
use crate::dbs::Auth;
|
use crate::dbs::Auth;
|
||||||
use crate::dbs::Runtime;
|
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
pub au: Auth, // Authentication info
|
pub au: Arc<Auth>, // Authentication info
|
||||||
pub ip: Option<String>, // Session ip address
|
pub ip: Option<String>, // Session ip address
|
||||||
pub or: Option<String>, // Session origin
|
pub or: Option<String>, // Session origin
|
||||||
pub id: Option<String>, // Session id
|
pub id: Option<String>, // Session id
|
||||||
|
@ -16,8 +16,16 @@ pub struct Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
pub fn context(&self) -> Runtime {
|
// Retrieves the selected namespace
|
||||||
let mut ctx = Context::background();
|
pub fn ns(&self) -> Option<Arc<String>> {
|
||||||
|
self.ns.to_owned().map(Arc::new)
|
||||||
|
}
|
||||||
|
// Retrieves the selected database
|
||||||
|
pub fn db(&self) -> Option<Arc<String>> {
|
||||||
|
self.db.to_owned().map(Arc::new)
|
||||||
|
}
|
||||||
|
// Convert a session into a runtime
|
||||||
|
pub fn context(&self, mut ctx: Context) -> Context {
|
||||||
// Add session value
|
// Add session value
|
||||||
let key = String::from("session");
|
let key = String::from("session");
|
||||||
let val: Value = self.into();
|
let val: Value = self.into();
|
||||||
|
@ -31,7 +39,7 @@ impl Session {
|
||||||
let val: Value = self.sd.to_owned().into();
|
let val: Value = self.sd.to_owned().into();
|
||||||
ctx.add_value(key, val);
|
ctx.add_value(key, val);
|
||||||
// Output context
|
// Output context
|
||||||
ctx.freeze()
|
ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,15 @@ use crate::ctx::Context;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
use crate::dbs::Runtime;
|
use crate::dbs::Runtime;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
|
use crate::kvs::Datastore;
|
||||||
use futures::lock::Mutex;
|
use futures::lock::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub async fn mock<'a>() -> (Runtime, Options, Transaction) {
|
pub async fn mock<'a>() -> (Runtime, Options, Transaction) {
|
||||||
let ctx = Context::default().freeze();
|
let ctx = Context::default().freeze();
|
||||||
let opt = Options::default();
|
let opt = Options::default();
|
||||||
let txn = Arc::new(Mutex::new(crate::kvs::Transaction::Mock));
|
let kvs = Datastore::new("memory").await.unwrap();
|
||||||
|
let txn = kvs.transaction(true, false).await.unwrap();
|
||||||
|
let txn = Arc::new(Mutex::new(txn));
|
||||||
(ctx, opt, txn)
|
(ctx, opt, txn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub type Variables = Option<HashMap<String, Value>>;
|
pub type Variables = Option<HashMap<String, Value>>;
|
||||||
|
|
||||||
pub(crate) trait Attach {
|
pub(crate) trait Attach {
|
||||||
fn attach(self, ctx: Arc<Context>) -> Arc<Context>;
|
fn attach(self, ctx: Context) -> Context;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attach for Variables {
|
impl Attach for Variables {
|
||||||
fn attach(self, ctx: Arc<Context>) -> Arc<Context> {
|
fn attach(self, mut ctx: Context) -> Context {
|
||||||
match self {
|
match self {
|
||||||
Some(m) => {
|
Some(m) => {
|
||||||
let mut ctx = Context::new(&ctx);
|
|
||||||
for (key, val) in m {
|
for (key, val) in m {
|
||||||
ctx.add_value(key, val);
|
ctx.add_value(key, val);
|
||||||
}
|
}
|
||||||
ctx.freeze()
|
ctx
|
||||||
}
|
}
|
||||||
None => ctx,
|
None => ctx,
|
||||||
}
|
}
|
||||||
|
|
186
lib/src/kvs/ds.rs
Normal file
186
lib/src/kvs/ds.rs
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
use super::tx::Transaction;
|
||||||
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Attach;
|
||||||
|
use crate::dbs::Executor;
|
||||||
|
use crate::dbs::Options;
|
||||||
|
use crate::dbs::Response;
|
||||||
|
use crate::dbs::Session;
|
||||||
|
use crate::dbs::Variables;
|
||||||
|
use crate::err::Error;
|
||||||
|
use crate::sql;
|
||||||
|
use crate::sql::query::Query;
|
||||||
|
|
||||||
|
/// The underlying datastore instance which stores the dataset.
|
||||||
|
pub struct Datastore {
|
||||||
|
pub(super) inner: Inner,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) enum Inner {
|
||||||
|
#[cfg(feature = "kv-echodb")]
|
||||||
|
Mem(super::mem::Datastore),
|
||||||
|
#[cfg(feature = "kv-indxdb")]
|
||||||
|
IxDB(super::ixdb::Datastore),
|
||||||
|
#[cfg(feature = "kv-yokudb")]
|
||||||
|
File(super::file::Datastore),
|
||||||
|
#[cfg(feature = "kv-tikv")]
|
||||||
|
TiKV(super::tikv::Datastore),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Datastore {
|
||||||
|
/// Creates a new datastore instance
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// # use surrealdb::Datastore;
|
||||||
|
/// # fn main() -> Result<()> {
|
||||||
|
/// let ds = Datastore::new("memory")?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Or to create a file-backed store:
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// # use surrealdb::Datastore;
|
||||||
|
/// # fn main() -> Result<()> {
|
||||||
|
/// let ds = Datastore::new("file://temp.db")?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Or to connect to a tikv-backed distributed store:
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// # use surrealdb::Datastore;
|
||||||
|
/// # fn main() -> Result<()> {
|
||||||
|
/// let ds = Datastore::new("tikv://127.0.0.1:2379")?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub async fn new(path: &str) -> Result<Datastore, Error> {
|
||||||
|
match path {
|
||||||
|
#[cfg(feature = "kv-echodb")]
|
||||||
|
"memory" => {
|
||||||
|
info!("Starting kvs store in {}", path);
|
||||||
|
super::mem::Datastore::new().await.map(|v| Datastore {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// Parse and initiate an IxDB database
|
||||||
|
#[cfg(feature = "kv-indxdb")]
|
||||||
|
s if s.starts_with("ixdb:") => {
|
||||||
|
info!("Starting kvs store at {}", path);
|
||||||
|
let s = s.trim_start_matches("ixdb://");
|
||||||
|
super::ixdb::Datastore::new(s).await.map(|v| Datastore {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// Parse and initiate an File database
|
||||||
|
#[cfg(feature = "kv-yokudb")]
|
||||||
|
s if s.starts_with("file:") => {
|
||||||
|
info!("Starting kvs store at {}", path);
|
||||||
|
let s = s.trim_start_matches("file://");
|
||||||
|
super::file::Datastore::new(s).await.map(|v| Datastore {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// Parse and initiate an TiKV database
|
||||||
|
#[cfg(feature = "kv-tikv")]
|
||||||
|
s if s.starts_with("tikv:") => {
|
||||||
|
info!("Starting kvs store at {}", path);
|
||||||
|
let s = s.trim_start_matches("tikv://");
|
||||||
|
super::tikv::Datastore::new(s).await.map(|v| Datastore {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// The datastore path is not valid
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Create a new transaction
|
||||||
|
pub async fn transaction(&self, write: bool, lock: bool) -> Result<Transaction, Error> {
|
||||||
|
match &self.inner {
|
||||||
|
#[cfg(feature = "kv-echodb")]
|
||||||
|
Inner::Mem(v) => {
|
||||||
|
let tx = v.transaction(write, lock).await?;
|
||||||
|
Ok(Transaction {
|
||||||
|
inner: super::tx::Inner::Mem(tx),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(feature = "kv-indxdb")]
|
||||||
|
Inner::IxDB(v) => {
|
||||||
|
let tx = v.transaction(write, lock).await?;
|
||||||
|
Ok(Transaction {
|
||||||
|
inner: super::tx::Inner::IxDB(tx),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(feature = "kv-yokudb")]
|
||||||
|
Inner::File(v) => {
|
||||||
|
let tx = v.transaction(write, lock).await?;
|
||||||
|
Ok(Transaction {
|
||||||
|
inner: super::tx::Inner::File(tx),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(feature = "kv-tikv")]
|
||||||
|
Inner::TiKV(v) => {
|
||||||
|
let tx = v.transaction(write, lock).await?;
|
||||||
|
Ok(Transaction {
|
||||||
|
inner: super::tx::Inner::TiKV(tx),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Execute a query
|
||||||
|
pub async fn execute(
|
||||||
|
&self,
|
||||||
|
txt: &str,
|
||||||
|
sess: &Session,
|
||||||
|
vars: Variables,
|
||||||
|
) -> Result<Vec<Response>, Error> {
|
||||||
|
// Create a new query options
|
||||||
|
let mut opt = Options::default();
|
||||||
|
// Create a new query executor
|
||||||
|
let mut exe = Executor::new(self);
|
||||||
|
// Create a default context
|
||||||
|
let ctx = Context::default();
|
||||||
|
// Start an execution context
|
||||||
|
let ctx = sess.context(ctx);
|
||||||
|
// Store the query variables
|
||||||
|
let ctx = vars.attach(ctx);
|
||||||
|
// Parse the SQL query text
|
||||||
|
let ast = sql::parse(txt)?;
|
||||||
|
// Freeze the context
|
||||||
|
let ctx = ctx.freeze();
|
||||||
|
// Process all statements
|
||||||
|
opt.auth = sess.au.clone();
|
||||||
|
opt.ns = sess.ns();
|
||||||
|
opt.db = sess.db();
|
||||||
|
exe.execute(ctx, opt, ast).await
|
||||||
|
}
|
||||||
|
/// Execute a query
|
||||||
|
pub async fn process(
|
||||||
|
&self,
|
||||||
|
ast: Query,
|
||||||
|
sess: &Session,
|
||||||
|
vars: Variables,
|
||||||
|
) -> Result<Vec<Response>, Error> {
|
||||||
|
// Create a new query options
|
||||||
|
let mut opt = Options::default();
|
||||||
|
// Create a new query executor
|
||||||
|
let mut exe = Executor::new(self);
|
||||||
|
// Create a default context
|
||||||
|
let ctx = Context::default();
|
||||||
|
// Start an execution context
|
||||||
|
let ctx = sess.context(ctx);
|
||||||
|
// Store the query variables
|
||||||
|
let ctx = vars.attach(ctx);
|
||||||
|
// Freeze the context
|
||||||
|
let ctx = ctx.freeze();
|
||||||
|
// Process all statements
|
||||||
|
opt.auth = sess.au.clone();
|
||||||
|
opt.ns = sess.ns();
|
||||||
|
opt.db = sess.db();
|
||||||
|
exe.execute(ctx, opt, ast).await
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,285 +0,0 @@
|
||||||
use super::Transaction;
|
|
||||||
use crate::err::Error;
|
|
||||||
use crate::kvs::Key;
|
|
||||||
use crate::kvs::Val;
|
|
||||||
use crate::sql;
|
|
||||||
use sql::statements::DefineDatabaseStatement;
|
|
||||||
use sql::statements::DefineEventStatement;
|
|
||||||
use sql::statements::DefineFieldStatement;
|
|
||||||
use sql::statements::DefineIndexStatement;
|
|
||||||
use sql::statements::DefineLoginStatement;
|
|
||||||
use sql::statements::DefineNamespaceStatement;
|
|
||||||
use sql::statements::DefineScopeStatement;
|
|
||||||
use sql::statements::DefineTableStatement;
|
|
||||||
use sql::statements::DefineTokenStatement;
|
|
||||||
use sql::statements::LiveStatement;
|
|
||||||
|
|
||||||
pub trait Convert<T> {
|
|
||||||
fn convert(self) -> T;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Convert<Vec<T>> for Vec<(Key, Val)>
|
|
||||||
where
|
|
||||||
T: From<Val>,
|
|
||||||
{
|
|
||||||
fn convert(self) -> Vec<T> {
|
|
||||||
self.into_iter().map(|(_, v)| v.into()).collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Transaction {
|
|
||||||
// Get all namespaces
|
|
||||||
pub async fn all_ns(&mut self) -> Result<Vec<DefineNamespaceStatement>, Error> {
|
|
||||||
let beg = crate::key::ns::prefix();
|
|
||||||
let end = crate::key::ns::suffix();
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all namespace logins
|
|
||||||
pub async fn all_nl(&mut self, ns: &str) -> Result<Vec<DefineLoginStatement>, Error> {
|
|
||||||
let beg = crate::key::nl::prefix(ns);
|
|
||||||
let end = crate::key::nl::suffix(ns);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all namespace tokens
|
|
||||||
pub async fn all_nt(&mut self, ns: &str) -> Result<Vec<DefineTokenStatement>, Error> {
|
|
||||||
let beg = crate::key::nt::prefix(ns);
|
|
||||||
let end = crate::key::nt::suffix(ns);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all databases
|
|
||||||
pub async fn all_db(&mut self, ns: &str) -> Result<Vec<DefineDatabaseStatement>, Error> {
|
|
||||||
let beg = crate::key::db::prefix(ns);
|
|
||||||
let end = crate::key::db::suffix(ns);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all database logins
|
|
||||||
pub async fn all_dl(&mut self, ns: &str, db: &str) -> Result<Vec<DefineLoginStatement>, Error> {
|
|
||||||
let beg = crate::key::dl::prefix(ns, db);
|
|
||||||
let end = crate::key::dl::suffix(ns, db);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all database tokens
|
|
||||||
pub async fn all_dt(&mut self, ns: &str, db: &str) -> Result<Vec<DefineTokenStatement>, Error> {
|
|
||||||
let beg = crate::key::dt::prefix(ns, db);
|
|
||||||
let end = crate::key::dt::suffix(ns, db);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all scopes
|
|
||||||
pub async fn all_sc(&mut self, ns: &str, db: &str) -> Result<Vec<DefineScopeStatement>, Error> {
|
|
||||||
let beg = crate::key::sc::prefix(ns, db);
|
|
||||||
let end = crate::key::sc::suffix(ns, db);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all scope tokens
|
|
||||||
pub async fn all_st(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
sc: &str,
|
|
||||||
) -> Result<Vec<DefineTokenStatement>, Error> {
|
|
||||||
let beg = crate::key::st::prefix(ns, db, sc);
|
|
||||||
let end = crate::key::st::suffix(ns, db, sc);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all tables
|
|
||||||
pub async fn all_tb(&mut self, ns: &str, db: &str) -> Result<Vec<DefineTableStatement>, Error> {
|
|
||||||
let beg = crate::key::tb::prefix(ns, db);
|
|
||||||
let end = crate::key::tb::suffix(ns, db);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all events
|
|
||||||
pub async fn all_ev(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
tb: &str,
|
|
||||||
) -> Result<Vec<DefineEventStatement>, Error> {
|
|
||||||
let beg = crate::key::ev::prefix(ns, db, tb);
|
|
||||||
let end = crate::key::ev::suffix(ns, db, tb);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all fields
|
|
||||||
pub async fn all_fd(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
tb: &str,
|
|
||||||
) -> Result<Vec<DefineFieldStatement>, Error> {
|
|
||||||
let beg = crate::key::fd::prefix(ns, db, tb);
|
|
||||||
let end = crate::key::fd::suffix(ns, db, tb);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all fields
|
|
||||||
pub async fn all_ix(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
tb: &str,
|
|
||||||
) -> Result<Vec<DefineIndexStatement>, Error> {
|
|
||||||
let beg = crate::key::ix::prefix(ns, db, tb);
|
|
||||||
let end = crate::key::ix::suffix(ns, db, tb);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all views
|
|
||||||
pub async fn all_ft(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
tb: &str,
|
|
||||||
) -> Result<Vec<DefineTableStatement>, Error> {
|
|
||||||
let beg = crate::key::ft::prefix(ns, db, tb);
|
|
||||||
let end = crate::key::ft::suffix(ns, db, tb);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
// Get all lives
|
|
||||||
pub async fn all_lv(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
tb: &str,
|
|
||||||
) -> Result<Vec<LiveStatement>, Error> {
|
|
||||||
let beg = crate::key::lv::prefix(ns, db, tb);
|
|
||||||
let end = crate::key::lv::suffix(ns, db, tb);
|
|
||||||
let val = self.getr(beg..end, u32::MAX).await?;
|
|
||||||
Ok(val.convert())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Transaction {
|
|
||||||
// Get a namespace
|
|
||||||
pub async fn get_ns(&mut self, ns: &str) -> Result<DefineNamespaceStatement, Error> {
|
|
||||||
let key = crate::key::ns::new(ns);
|
|
||||||
let val = self.get(key).await?.ok_or(Error::NsNotFound)?;
|
|
||||||
Ok(val.into())
|
|
||||||
}
|
|
||||||
// Get a namespace login
|
|
||||||
pub async fn get_nl(&mut self, ns: &str, nl: &str) -> Result<DefineLoginStatement, Error> {
|
|
||||||
let key = crate::key::nl::new(ns, nl);
|
|
||||||
let val = self.get(key).await?.ok_or(Error::NlNotFound)?;
|
|
||||||
Ok(val.into())
|
|
||||||
}
|
|
||||||
// Get a namespace token
|
|
||||||
pub async fn get_nt(&mut self, ns: &str, nt: &str) -> Result<DefineTokenStatement, Error> {
|
|
||||||
let key = crate::key::nt::new(ns, nt);
|
|
||||||
let val = self.get(key).await?.ok_or(Error::NtNotFound)?;
|
|
||||||
Ok(val.into())
|
|
||||||
}
|
|
||||||
// Get a database
|
|
||||||
pub async fn get_db(&mut self, ns: &str, db: &str) -> Result<DefineDatabaseStatement, Error> {
|
|
||||||
let key = crate::key::db::new(ns, db);
|
|
||||||
let val = self.get(key).await?.ok_or(Error::DbNotFound)?;
|
|
||||||
Ok(val.into())
|
|
||||||
}
|
|
||||||
// Get a database login
|
|
||||||
pub async fn get_dl(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
dl: &str,
|
|
||||||
) -> Result<DefineLoginStatement, Error> {
|
|
||||||
let key = crate::key::dl::new(ns, db, dl);
|
|
||||||
let val = self.get(key).await?.ok_or(Error::DlNotFound)?;
|
|
||||||
Ok(val.into())
|
|
||||||
}
|
|
||||||
// Get a database token
|
|
||||||
pub async fn get_dt(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
dt: &str,
|
|
||||||
) -> Result<DefineTokenStatement, Error> {
|
|
||||||
let key = crate::key::dt::new(ns, db, dt);
|
|
||||||
let val = self.get(key).await?.ok_or(Error::DtNotFound)?;
|
|
||||||
Ok(val.into())
|
|
||||||
}
|
|
||||||
// Get a scope
|
|
||||||
pub async fn get_sc(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
sc: &str,
|
|
||||||
) -> Result<DefineScopeStatement, Error> {
|
|
||||||
let key = crate::key::sc::new(ns, db, sc);
|
|
||||||
let val = self.get(key).await?.ok_or(Error::ScNotFound)?;
|
|
||||||
Ok(val.into())
|
|
||||||
}
|
|
||||||
// Get a scope token
|
|
||||||
pub async fn get_st(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
sc: &str,
|
|
||||||
st: &str,
|
|
||||||
) -> Result<DefineTokenStatement, Error> {
|
|
||||||
let key = crate::key::st::new(ns, db, sc, st);
|
|
||||||
let val = self.get(key).await?.ok_or(Error::StNotFound)?;
|
|
||||||
Ok(val.into())
|
|
||||||
}
|
|
||||||
// Get a table
|
|
||||||
pub async fn get_tb(
|
|
||||||
&mut self,
|
|
||||||
ns: &str,
|
|
||||||
db: &str,
|
|
||||||
tb: &str,
|
|
||||||
) -> Result<DefineTableStatement, Error> {
|
|
||||||
let key = crate::key::tb::new(ns, db, tb);
|
|
||||||
let val = self.get(key).await?.ok_or(Error::TbNotFound)?;
|
|
||||||
Ok(val.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Transaction {
|
|
||||||
// Get all namespaces
|
|
||||||
pub async fn add_ns(&mut self, ns: &str) -> Result<(), Error> {
|
|
||||||
let key = crate::key::ns::new(ns);
|
|
||||||
let _ = self
|
|
||||||
.put(
|
|
||||||
key,
|
|
||||||
DefineNamespaceStatement {
|
|
||||||
name: ns.to_owned(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
// Get all namespace logins
|
|
||||||
pub async fn add_db(&mut self, ns: &str, db: &str) -> Result<(), Error> {
|
|
||||||
let key = crate::key::db::new(ns, db);
|
|
||||||
let _ = self
|
|
||||||
.put(
|
|
||||||
key,
|
|
||||||
DefineDatabaseStatement {
|
|
||||||
name: db.to_owned(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
// Get all namespace tokens
|
|
||||||
pub async fn add_tb(&mut self, ns: &str, db: &str, tb: &str) -> Result<(), Error> {
|
|
||||||
let key = crate::key::tb::new(ns, db, tb);
|
|
||||||
let _ = self
|
|
||||||
.put(
|
|
||||||
key,
|
|
||||||
DefineTableStatement {
|
|
||||||
name: tb.to_owned(),
|
|
||||||
..DefineTableStatement::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +1,31 @@
|
||||||
|
/// The key part of a key-value pair. An alias for [`Vec<u8>`].
|
||||||
pub type Key = Vec<u8>;
|
pub type Key = Vec<u8>;
|
||||||
|
|
||||||
|
/// The value part of a key-value pair. An alias for [`Vec<u8>`].
|
||||||
pub type Val = Vec<u8>;
|
pub type Val = Vec<u8>;
|
||||||
|
|
||||||
|
// This trait appends an element to a collection, and allows chaining
|
||||||
|
pub(super) trait Add<T> {
|
||||||
|
fn add(self, v: T) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<u8> for Vec<u8> {
|
||||||
|
fn add(mut self, v: u8) -> Self {
|
||||||
|
self.push(v);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This trait converts a collection of key-value pairs into the desired type
|
||||||
|
pub(super) trait Convert<T> {
|
||||||
|
fn convert(self) -> T;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Convert<Vec<T>> for Vec<(Key, Val)>
|
||||||
|
where
|
||||||
|
T: From<Val>,
|
||||||
|
{
|
||||||
|
fn convert(self) -> Vec<T> {
|
||||||
|
self.into_iter().map(|(_, v)| v.into()).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
mod ex;
|
mod ds;
|
||||||
mod file;
|
mod file;
|
||||||
mod ixdb;
|
mod ixdb;
|
||||||
mod kv;
|
mod kv;
|
||||||
|
@ -6,99 +6,6 @@ mod mem;
|
||||||
mod tikv;
|
mod tikv;
|
||||||
mod tx;
|
mod tx;
|
||||||
|
|
||||||
|
pub use self::ds::*;
|
||||||
pub use self::kv::*;
|
pub use self::kv::*;
|
||||||
pub use self::tx::*;
|
pub use self::tx::*;
|
||||||
|
|
||||||
use crate::err::Error;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub type Store = Arc<Datastore>;
|
|
||||||
|
|
||||||
pub enum Datastore {
|
|
||||||
Mock,
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
|
||||||
Mem(mem::Datastore),
|
|
||||||
#[cfg(feature = "kv-indxdb")]
|
|
||||||
IxDB(ixdb::Datastore),
|
|
||||||
#[cfg(feature = "kv-yokudb")]
|
|
||||||
File(file::Datastore),
|
|
||||||
#[cfg(feature = "kv-tikv")]
|
|
||||||
TiKV(tikv::Datastore),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Transaction {
|
|
||||||
Mock,
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
|
||||||
Mem(mem::Transaction),
|
|
||||||
#[cfg(feature = "kv-indxdb")]
|
|
||||||
IxDB(ixdb::Transaction),
|
|
||||||
#[cfg(feature = "kv-yokudb")]
|
|
||||||
File(file::Transaction),
|
|
||||||
#[cfg(feature = "kv-tikv")]
|
|
||||||
TiKV(tikv::Transaction),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Datastore {
|
|
||||||
// Create a new datastore
|
|
||||||
pub async fn new(path: &str) -> Result<Self, Error> {
|
|
||||||
match path {
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
|
||||||
"memory" => {
|
|
||||||
info!("Starting kvs store in {}", path);
|
|
||||||
mem::Datastore::new().await.map(Datastore::Mem)
|
|
||||||
}
|
|
||||||
// Parse and initiate an IxDB database
|
|
||||||
#[cfg(feature = "kv-indxdb")]
|
|
||||||
s if s.starts_with("ixdb:") => {
|
|
||||||
info!("Starting kvs store at {}", path);
|
|
||||||
let s = s.trim_start_matches("ixdb://");
|
|
||||||
ixdb::Datastore::new(s).await.map(Datastore::IxDB)
|
|
||||||
}
|
|
||||||
// Parse and initiate an File database
|
|
||||||
#[cfg(feature = "kv-yokudb")]
|
|
||||||
s if s.starts_with("file:") => {
|
|
||||||
info!("Starting kvs store at {}", path);
|
|
||||||
let s = s.trim_start_matches("file://");
|
|
||||||
file::Datastore::new(s).await.map(Datastore::File)
|
|
||||||
}
|
|
||||||
// Parse and initiate an TiKV database
|
|
||||||
#[cfg(feature = "kv-tikv")]
|
|
||||||
s if s.starts_with("tikv:") => {
|
|
||||||
info!("Starting kvs store at {}", path);
|
|
||||||
let s = s.trim_start_matches("tikv://");
|
|
||||||
tikv::Datastore::new(s).await.map(Datastore::TiKV)
|
|
||||||
}
|
|
||||||
// The datastore path is not valid
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Create a new transaction
|
|
||||||
pub async fn transaction(&self, write: bool, lock: bool) -> Result<Transaction, Error> {
|
|
||||||
match self {
|
|
||||||
Datastore::Mock => {
|
|
||||||
let tx = Transaction::Mock;
|
|
||||||
Ok(tx)
|
|
||||||
}
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
|
||||||
Datastore::Mem(v) => {
|
|
||||||
let tx = v.transaction(write, lock).await?;
|
|
||||||
Ok(Transaction::Mem(tx))
|
|
||||||
}
|
|
||||||
#[cfg(feature = "kv-indxdb")]
|
|
||||||
Datastore::IxDB(v) => {
|
|
||||||
let tx = v.transaction(write, lock).await?;
|
|
||||||
Ok(Transaction::IxDB(tx))
|
|
||||||
}
|
|
||||||
#[cfg(feature = "kv-yokudb")]
|
|
||||||
Datastore::File(v) => {
|
|
||||||
let tx = v.transaction(write, lock).await?;
|
|
||||||
Ok(Transaction::File(tx))
|
|
||||||
}
|
|
||||||
#[cfg(feature = "kv-tikv")]
|
|
||||||
Datastore::TiKV(v) => {
|
|
||||||
let tx = v.transaction(write, lock).await?;
|
|
||||||
Ok(Transaction::TiKV(tx))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,204 +1,311 @@
|
||||||
use super::Transaction;
|
use super::kv::Add;
|
||||||
|
use super::kv::Convert;
|
||||||
|
use super::Key;
|
||||||
|
use super::Val;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::kvs::Key;
|
use crate::sql;
|
||||||
use crate::kvs::Val;
|
use sql::statements::DefineDatabaseStatement;
|
||||||
|
use sql::statements::DefineEventStatement;
|
||||||
|
use sql::statements::DefineFieldStatement;
|
||||||
|
use sql::statements::DefineIndexStatement;
|
||||||
|
use sql::statements::DefineLoginStatement;
|
||||||
|
use sql::statements::DefineNamespaceStatement;
|
||||||
|
use sql::statements::DefineScopeStatement;
|
||||||
|
use sql::statements::DefineTableStatement;
|
||||||
|
use sql::statements::DefineTokenStatement;
|
||||||
|
use sql::statements::LiveStatement;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
trait Add<T> {
|
/// A set of undoable updates and requests against a dataset.
|
||||||
fn add(self, v: T) -> Self;
|
pub struct Transaction {
|
||||||
|
pub(super) inner: Inner,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add<u8> for Vec<u8> {
|
pub(super) enum Inner {
|
||||||
fn add(mut self, v: u8) -> Self {
|
#[cfg(feature = "kv-echodb")]
|
||||||
self.push(v);
|
Mem(super::mem::Transaction),
|
||||||
self
|
#[cfg(feature = "kv-indxdb")]
|
||||||
}
|
IxDB(super::ixdb::Transaction),
|
||||||
|
#[cfg(feature = "kv-yokudb")]
|
||||||
|
File(super::file::Transaction),
|
||||||
|
#[cfg(feature = "kv-tikv")]
|
||||||
|
TiKV(super::tikv::Transaction),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
// Check if closed
|
/// Check if transactions is finished.
|
||||||
|
///
|
||||||
|
/// If the transaction has been cancelled or committed,
|
||||||
|
/// then this function will return [`true`], and any further
|
||||||
|
/// calls to functions on this transaction will result
|
||||||
|
/// in a [`Error::TxFinished`] error.
|
||||||
pub async fn closed(&self) -> bool {
|
pub async fn closed(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.closed(),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.closed(),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.closed(),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.closed(),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.closed(),
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.closed(),
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.closed(),
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.closed(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cancel a transaction
|
/// Cancel a transaction.
|
||||||
|
///
|
||||||
|
/// This reverses all changes made within the transaction.
|
||||||
pub async fn cancel(&mut self) -> Result<(), Error> {
|
pub async fn cancel(&mut self) -> Result<(), Error> {
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.cancel(),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.cancel(),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.cancel(),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.cancel(),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.cancel().await,
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.cancel().await,
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.cancel().await,
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.cancel().await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Commit a transaction
|
/// Commit a transaction.
|
||||||
|
///
|
||||||
|
/// This attempts to commit all changes made within the transaction.
|
||||||
pub async fn commit(&mut self) -> Result<(), Error> {
|
pub async fn commit(&mut self) -> Result<(), Error> {
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.commit(),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.commit(),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.commit(),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.commit(),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.commit().await,
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.commit().await,
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.commit().await,
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.commit().await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete a key
|
/// Delete a key from the datastore.
|
||||||
pub async fn del<K>(&mut self, key: K) -> Result<(), Error>
|
pub async fn del<K>(&mut self, key: K) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.del(key),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.del(key),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.del(key),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.del(key),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.del(key).await,
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.del(key).await,
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.del(key).await,
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.del(key).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if a key exists
|
/// Check if a key exists in the datastore.
|
||||||
pub async fn exi<K>(&mut self, key: K) -> Result<bool, Error>
|
pub async fn exi<K>(&mut self, key: K) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.exi(key),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.exi(key),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.exi(key),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.exi(key),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.exi(key).await,
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.exi(key).await,
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.exi(key).await,
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.exi(key).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fetch a key from the database
|
/// Fetch a key from the datastore.
|
||||||
pub async fn get<K>(&mut self, key: K) -> Result<Option<Val>, Error>
|
pub async fn get<K>(&mut self, key: K) -> Result<Option<Val>, Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.get(key),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.get(key),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.get(key),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.get(key),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.get(key).await,
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.get(key).await,
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.get(key).await,
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.get(key).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Insert or update a key in the database
|
/// Insert or update a key in the datastore.
|
||||||
pub async fn set<K, V>(&mut self, key: K, val: V) -> Result<(), Error>
|
pub async fn set<K, V>(&mut self, key: K, val: V) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
V: Into<Key>,
|
V: Into<Key>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.set(key, val),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.set(key, val),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.set(key, val),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.set(key, val),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.set(key, val).await,
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.set(key, val).await,
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.set(key, val).await,
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.set(key, val).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Insert a key if it doesn't exist in the database
|
/// Insert a key if it doesn't exist in the datastore.
|
||||||
pub async fn put<K, V>(&mut self, key: K, val: V) -> Result<(), Error>
|
pub async fn put<K, V>(&mut self, key: K, val: V) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
V: Into<Key>,
|
V: Into<Key>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.put(key, val),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.put(key, val),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.put(key, val),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.put(key, val),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.put(key, val).await,
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.put(key, val).await,
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.put(key, val).await,
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.put(key, val).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Retrieve a range of keys from the databases
|
/// Retrieve a specific range of keys from the datastore.
|
||||||
|
///
|
||||||
|
/// This function fetches the full range of key-value pairs, in a single request to the underlying datastore.
|
||||||
pub async fn scan<K>(&mut self, rng: Range<K>, limit: u32) -> Result<Vec<(Key, Val)>, Error>
|
pub async fn scan<K>(&mut self, rng: Range<K>, limit: u32) -> Result<Vec<(Key, Val)>, Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.scan(rng, limit),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.scan(rng, limit),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.scan(rng, limit),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.scan(rng, limit),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.scan(rng, limit).await,
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.scan(rng, limit).await,
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.scan(rng, limit).await,
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.scan(rng, limit).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete a range of keys from the databases
|
/// Update a key in the datastore if the current value matches a condition.
|
||||||
pub async fn putc<K, V>(&mut self, key: K, val: V, chk: Option<V>) -> Result<(), Error>
|
pub async fn putc<K, V>(&mut self, key: K, val: V, chk: Option<V>) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
V: Into<Val>,
|
V: Into<Val>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.putc(key, val, chk),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.putc(key, val, chk),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.putc(key, val, chk),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.putc(key, val, chk),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.putc(key, val, chk).await,
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.putc(key, val, chk).await,
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.putc(key, val, chk).await,
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.putc(key, val, chk).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete a range of keys from the databases
|
/// Delete a key from the datastore if the current value matches a condition.
|
||||||
pub async fn delc<K, V>(&mut self, key: K, chk: Option<V>) -> Result<(), Error>
|
pub async fn delc<K, V>(&mut self, key: K, chk: Option<V>) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
V: Into<Val>,
|
V: Into<Val>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Transaction::Mock => unreachable!(),
|
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
Transaction::Mem(v) => v.delc(key, chk),
|
Transaction {
|
||||||
|
inner: Inner::Mem(v),
|
||||||
|
} => v.delc(key, chk),
|
||||||
#[cfg(feature = "kv-yokudb")]
|
#[cfg(feature = "kv-yokudb")]
|
||||||
Transaction::File(v) => v.delc(key, chk),
|
Transaction {
|
||||||
|
inner: Inner::File(v),
|
||||||
|
} => v.delc(key, chk),
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
Transaction::IxDB(v) => v.delc(key, chk).await,
|
Transaction {
|
||||||
|
inner: Inner::IxDB(v),
|
||||||
|
} => v.delc(key, chk).await,
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
Transaction::TiKV(v) => v.delc(key, chk).await,
|
Transaction {
|
||||||
|
inner: Inner::TiKV(v),
|
||||||
|
} => v.delc(key, chk).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Retrieve a range of keys from the databases
|
/// Retrieve a specific range of keys from the datastore.
|
||||||
|
///
|
||||||
|
/// This function fetches key-value pairs from the underlying datastore in batches of 1000.
|
||||||
pub async fn getr<K>(&mut self, rng: Range<K>, limit: u32) -> Result<Vec<(Key, Val)>, Error>
|
pub async fn getr<K>(&mut self, rng: Range<K>, limit: u32) -> Result<Vec<(Key, Val)>, Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
|
@ -246,7 +353,9 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
// Delete a range of keys from the databases
|
/// Delete a range of keys from the datastore.
|
||||||
|
///
|
||||||
|
/// This function fetches key-value pairs from the underlying datastore in batches of 1000.
|
||||||
pub async fn delr<K>(&mut self, rng: Range<K>, limit: u32) -> Result<(), Error>
|
pub async fn delr<K>(&mut self, rng: Range<K>, limit: u32) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
|
@ -293,7 +402,9 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
// Retrieve a prefix of keys from the databases
|
/// Retrieve a specific prefix of keys from the datastore.
|
||||||
|
///
|
||||||
|
/// This function fetches key-value pairs from the underlying datastore in batches of 1000.
|
||||||
pub async fn getp<K>(&mut self, key: K, limit: u32) -> Result<Vec<(Key, Val)>, Error>
|
pub async fn getp<K>(&mut self, key: K, limit: u32) -> Result<Vec<(Key, Val)>, Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
|
@ -341,7 +452,9 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
// Delete a prefix of keys from the databases
|
/// Delete a prefix of keys from the datastore.
|
||||||
|
///
|
||||||
|
/// This function fetches key-value pairs from the underlying datastore in batches of 1000.
|
||||||
pub async fn delp<K>(&mut self, key: K, limit: u32) -> Result<(), Error>
|
pub async fn delp<K>(&mut self, key: K, limit: u32) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
K: Into<Key>,
|
K: Into<Key>,
|
||||||
|
@ -388,4 +501,252 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
/// Retrieve all namespace definitions in a datastore.
|
||||||
|
pub async fn all_ns(&mut self) -> Result<Vec<DefineNamespaceStatement>, Error> {
|
||||||
|
let beg = crate::key::ns::prefix();
|
||||||
|
let end = crate::key::ns::suffix();
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all namespace login definitions for a specific namespace.
|
||||||
|
pub async fn all_nl(&mut self, ns: &str) -> Result<Vec<DefineLoginStatement>, Error> {
|
||||||
|
let beg = crate::key::nl::prefix(ns);
|
||||||
|
let end = crate::key::nl::suffix(ns);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all namespace token definitions for a specific namespace.
|
||||||
|
pub async fn all_nt(&mut self, ns: &str) -> Result<Vec<DefineTokenStatement>, Error> {
|
||||||
|
let beg = crate::key::nt::prefix(ns);
|
||||||
|
let end = crate::key::nt::suffix(ns);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all database definitions for a specific namespace.
|
||||||
|
pub async fn all_db(&mut self, ns: &str) -> Result<Vec<DefineDatabaseStatement>, Error> {
|
||||||
|
let beg = crate::key::db::prefix(ns);
|
||||||
|
let end = crate::key::db::suffix(ns);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all database login definitions for a specific database.
|
||||||
|
pub async fn all_dl(&mut self, ns: &str, db: &str) -> Result<Vec<DefineLoginStatement>, Error> {
|
||||||
|
let beg = crate::key::dl::prefix(ns, db);
|
||||||
|
let end = crate::key::dl::suffix(ns, db);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all database token definitions for a specific database.
|
||||||
|
pub async fn all_dt(&mut self, ns: &str, db: &str) -> Result<Vec<DefineTokenStatement>, Error> {
|
||||||
|
let beg = crate::key::dt::prefix(ns, db);
|
||||||
|
let end = crate::key::dt::suffix(ns, db);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all scope definitions for a specific database.
|
||||||
|
pub async fn all_sc(&mut self, ns: &str, db: &str) -> Result<Vec<DefineScopeStatement>, Error> {
|
||||||
|
let beg = crate::key::sc::prefix(ns, db);
|
||||||
|
let end = crate::key::sc::suffix(ns, db);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all scope token definitions for a scope.
|
||||||
|
pub async fn all_st(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
sc: &str,
|
||||||
|
) -> Result<Vec<DefineTokenStatement>, Error> {
|
||||||
|
let beg = crate::key::st::prefix(ns, db, sc);
|
||||||
|
let end = crate::key::st::suffix(ns, db, sc);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all table definitions for a specific database.
|
||||||
|
pub async fn all_tb(&mut self, ns: &str, db: &str) -> Result<Vec<DefineTableStatement>, Error> {
|
||||||
|
let beg = crate::key::tb::prefix(ns, db);
|
||||||
|
let end = crate::key::tb::suffix(ns, db);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all event definitions for a specific table.
|
||||||
|
pub async fn all_ev(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
tb: &str,
|
||||||
|
) -> Result<Vec<DefineEventStatement>, Error> {
|
||||||
|
let beg = crate::key::ev::prefix(ns, db, tb);
|
||||||
|
let end = crate::key::ev::suffix(ns, db, tb);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all field definitions for a specific table.
|
||||||
|
pub async fn all_fd(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
tb: &str,
|
||||||
|
) -> Result<Vec<DefineFieldStatement>, Error> {
|
||||||
|
let beg = crate::key::fd::prefix(ns, db, tb);
|
||||||
|
let end = crate::key::fd::suffix(ns, db, tb);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all index definitions for a specific table.
|
||||||
|
pub async fn all_ix(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
tb: &str,
|
||||||
|
) -> Result<Vec<DefineIndexStatement>, Error> {
|
||||||
|
let beg = crate::key::ix::prefix(ns, db, tb);
|
||||||
|
let end = crate::key::ix::suffix(ns, db, tb);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all view definitions for a specific table.
|
||||||
|
pub async fn all_ft(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
tb: &str,
|
||||||
|
) -> Result<Vec<DefineTableStatement>, Error> {
|
||||||
|
let beg = crate::key::ft::prefix(ns, db, tb);
|
||||||
|
let end = crate::key::ft::suffix(ns, db, tb);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve all live definitions for a specific table.
|
||||||
|
pub async fn all_lv(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
tb: &str,
|
||||||
|
) -> Result<Vec<LiveStatement>, Error> {
|
||||||
|
let beg = crate::key::lv::prefix(ns, db, tb);
|
||||||
|
let end = crate::key::lv::suffix(ns, db, tb);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
Ok(val.convert())
|
||||||
|
}
|
||||||
|
/// Retrieve a specific namespace definition.
|
||||||
|
pub async fn get_ns(&mut self, ns: &str) -> Result<DefineNamespaceStatement, Error> {
|
||||||
|
let key = crate::key::ns::new(ns);
|
||||||
|
let val = self.get(key).await?.ok_or(Error::NsNotFound)?;
|
||||||
|
Ok(val.into())
|
||||||
|
}
|
||||||
|
/// Retrieve a specific namespace login definition.
|
||||||
|
pub async fn get_nl(&mut self, ns: &str, nl: &str) -> Result<DefineLoginStatement, Error> {
|
||||||
|
let key = crate::key::nl::new(ns, nl);
|
||||||
|
let val = self.get(key).await?.ok_or(Error::NlNotFound)?;
|
||||||
|
Ok(val.into())
|
||||||
|
}
|
||||||
|
/// Retrieve a specific namespace token definition.
|
||||||
|
pub async fn get_nt(&mut self, ns: &str, nt: &str) -> Result<DefineTokenStatement, Error> {
|
||||||
|
let key = crate::key::nt::new(ns, nt);
|
||||||
|
let val = self.get(key).await?.ok_or(Error::NtNotFound)?;
|
||||||
|
Ok(val.into())
|
||||||
|
}
|
||||||
|
/// Retrieve a specific database definition.
|
||||||
|
pub async fn get_db(&mut self, ns: &str, db: &str) -> Result<DefineDatabaseStatement, Error> {
|
||||||
|
let key = crate::key::db::new(ns, db);
|
||||||
|
let val = self.get(key).await?.ok_or(Error::DbNotFound)?;
|
||||||
|
Ok(val.into())
|
||||||
|
}
|
||||||
|
/// Retrieve a specific database login definition.
|
||||||
|
pub async fn get_dl(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
dl: &str,
|
||||||
|
) -> Result<DefineLoginStatement, Error> {
|
||||||
|
let key = crate::key::dl::new(ns, db, dl);
|
||||||
|
let val = self.get(key).await?.ok_or(Error::DlNotFound)?;
|
||||||
|
Ok(val.into())
|
||||||
|
}
|
||||||
|
/// Retrieve a specific database token definition.
|
||||||
|
pub async fn get_dt(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
dt: &str,
|
||||||
|
) -> Result<DefineTokenStatement, Error> {
|
||||||
|
let key = crate::key::dt::new(ns, db, dt);
|
||||||
|
let val = self.get(key).await?.ok_or(Error::DtNotFound)?;
|
||||||
|
Ok(val.into())
|
||||||
|
}
|
||||||
|
/// Retrieve a specific scope definition.
|
||||||
|
pub async fn get_sc(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
sc: &str,
|
||||||
|
) -> Result<DefineScopeStatement, Error> {
|
||||||
|
let key = crate::key::sc::new(ns, db, sc);
|
||||||
|
let val = self.get(key).await?.ok_or(Error::ScNotFound)?;
|
||||||
|
Ok(val.into())
|
||||||
|
}
|
||||||
|
/// Retrieve a specific scope token definition.
|
||||||
|
pub async fn get_st(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
sc: &str,
|
||||||
|
st: &str,
|
||||||
|
) -> Result<DefineTokenStatement, Error> {
|
||||||
|
let key = crate::key::st::new(ns, db, sc, st);
|
||||||
|
let val = self.get(key).await?.ok_or(Error::StNotFound)?;
|
||||||
|
Ok(val.into())
|
||||||
|
}
|
||||||
|
/// Retrieve a specific table definition.
|
||||||
|
pub async fn get_tb(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
tb: &str,
|
||||||
|
) -> Result<DefineTableStatement, Error> {
|
||||||
|
let key = crate::key::tb::new(ns, db, tb);
|
||||||
|
let val = self.get(key).await?.ok_or(Error::TbNotFound)?;
|
||||||
|
Ok(val.into())
|
||||||
|
}
|
||||||
|
/// Add a namespace with a default configuration.
|
||||||
|
pub async fn add_ns(&mut self, ns: &str) -> Result<(), Error> {
|
||||||
|
let key = crate::key::ns::new(ns);
|
||||||
|
let _ = self
|
||||||
|
.put(
|
||||||
|
key,
|
||||||
|
DefineNamespaceStatement {
|
||||||
|
name: ns.to_owned(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
/// Add a database with a default configuration.
|
||||||
|
pub async fn add_db(&mut self, ns: &str, db: &str) -> Result<(), Error> {
|
||||||
|
let key = crate::key::db::new(ns, db);
|
||||||
|
let _ = self
|
||||||
|
.put(
|
||||||
|
key,
|
||||||
|
DefineDatabaseStatement {
|
||||||
|
name: db.to_owned(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
/// Add a table with a default configuration.
|
||||||
|
pub async fn add_tb(&mut self, ns: &str, db: &str, tb: &str) -> Result<(), Error> {
|
||||||
|
let key = crate::key::tb::new(ns, db, tb);
|
||||||
|
let _ = self
|
||||||
|
.put(
|
||||||
|
key,
|
||||||
|
DefineTableStatement {
|
||||||
|
name: tb.to_owned(),
|
||||||
|
..DefineTableStatement::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,6 @@ pub mod sql;
|
||||||
|
|
||||||
pub use err::Error;
|
pub use err::Error;
|
||||||
|
|
||||||
pub use dbs::execute;
|
|
||||||
pub use dbs::process;
|
|
||||||
pub use dbs::Auth;
|
pub use dbs::Auth;
|
||||||
pub use dbs::Response;
|
pub use dbs::Response;
|
||||||
pub use dbs::Session;
|
pub use dbs::Session;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::sync::Arc;
|
||||||
use surrealdb::Auth;
|
use surrealdb::Auth;
|
||||||
use surrealdb::Session;
|
use surrealdb::Session;
|
||||||
use warp::Filter;
|
use warp::Filter;
|
||||||
|
@ -32,7 +33,7 @@ fn process(
|
||||||
) -> Session {
|
) -> Session {
|
||||||
// Create session
|
// Create session
|
||||||
let conf = Session {
|
let conf = Session {
|
||||||
au: Auth::default(),
|
au: Arc::new(Auth::default()),
|
||||||
ip: ip.map(|v| v.to_string()),
|
ip: ip.map(|v| v.to_string()),
|
||||||
or,
|
or,
|
||||||
id,
|
id,
|
||||||
|
|
|
@ -106,7 +106,7 @@ async fn select_all(
|
||||||
table: String,
|
table: String,
|
||||||
query: Query,
|
query: Query,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
let db = DB.get().unwrap().clone();
|
let db = DB.get().unwrap();
|
||||||
let sql = format!(
|
let sql = format!(
|
||||||
"SELECT * FROM type::table($table) LIMIT {l} START {s}",
|
"SELECT * FROM type::table($table) LIMIT {l} START {s}",
|
||||||
l = query.limit.unwrap_or_else(|| String::from("100")),
|
l = query.limit.unwrap_or_else(|| String::from("100")),
|
||||||
|
@ -115,7 +115,7 @@ async fn select_all(
|
||||||
let vars = map! {
|
let vars = map! {
|
||||||
String::from("table") => Value::from(table),
|
String::from("table") => Value::from(table),
|
||||||
};
|
};
|
||||||
match surrealdb::execute(db, sql.as_str(), session, Some(vars)).await {
|
match db.execute(sql.as_str(), &session, Some(vars)).await {
|
||||||
Ok(ref res) => match output.as_ref() {
|
Ok(ref res) => match output.as_ref() {
|
||||||
"application/json" => Ok(output::json(res)),
|
"application/json" => Ok(output::json(res)),
|
||||||
"application/cbor" => Ok(output::cbor(res)),
|
"application/cbor" => Ok(output::cbor(res)),
|
||||||
|
@ -132,7 +132,7 @@ async fn create_all(
|
||||||
table: String,
|
table: String,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
let db = DB.get().unwrap().clone();
|
let db = DB.get().unwrap();
|
||||||
let data = str::from_utf8(&body).unwrap();
|
let data = str::from_utf8(&body).unwrap();
|
||||||
match surrealdb::sql::json(data) {
|
match surrealdb::sql::json(data) {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
|
@ -141,7 +141,7 @@ async fn create_all(
|
||||||
String::from("table") => Value::from(table),
|
String::from("table") => Value::from(table),
|
||||||
String::from("data") => data,
|
String::from("data") => data,
|
||||||
};
|
};
|
||||||
match surrealdb::execute(db, sql, session, Some(vars)).await {
|
match db.execute(sql, &session, Some(vars)).await {
|
||||||
Ok(res) => match output.as_ref() {
|
Ok(res) => match output.as_ref() {
|
||||||
"application/json" => Ok(output::json(&res)),
|
"application/json" => Ok(output::json(&res)),
|
||||||
"application/cbor" => Ok(output::cbor(&res)),
|
"application/cbor" => Ok(output::cbor(&res)),
|
||||||
|
@ -160,12 +160,12 @@ async fn delete_all(
|
||||||
output: String,
|
output: String,
|
||||||
table: String,
|
table: String,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
let db = DB.get().unwrap().clone();
|
let db = DB.get().unwrap();
|
||||||
let sql = "DELETE type::table($table)";
|
let sql = "DELETE type::table($table)";
|
||||||
let vars = map! {
|
let vars = map! {
|
||||||
String::from("table") => Value::from(table),
|
String::from("table") => Value::from(table),
|
||||||
};
|
};
|
||||||
match surrealdb::execute(db, sql, session, Some(vars)).await {
|
match db.execute(sql, &session, Some(vars)).await {
|
||||||
Ok(res) => match output.as_ref() {
|
Ok(res) => match output.as_ref() {
|
||||||
"application/json" => Ok(output::json(&res)),
|
"application/json" => Ok(output::json(&res)),
|
||||||
"application/cbor" => Ok(output::cbor(&res)),
|
"application/cbor" => Ok(output::cbor(&res)),
|
||||||
|
@ -186,13 +186,13 @@ async fn select_one(
|
||||||
table: String,
|
table: String,
|
||||||
id: String,
|
id: String,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
let db = DB.get().unwrap().clone();
|
let db = DB.get().unwrap();
|
||||||
let sql = "SELECT * FROM type::thing($table, $id)";
|
let sql = "SELECT * FROM type::thing($table, $id)";
|
||||||
let vars = map! {
|
let vars = map! {
|
||||||
String::from("table") => Value::from(table),
|
String::from("table") => Value::from(table),
|
||||||
String::from("id") => Value::from(id),
|
String::from("id") => Value::from(id),
|
||||||
};
|
};
|
||||||
match surrealdb::execute(db, sql, session, Some(vars)).await {
|
match db.execute(sql, &session, Some(vars)).await {
|
||||||
Ok(res) => match output.as_ref() {
|
Ok(res) => match output.as_ref() {
|
||||||
"application/json" => Ok(output::json(&res)),
|
"application/json" => Ok(output::json(&res)),
|
||||||
"application/cbor" => Ok(output::cbor(&res)),
|
"application/cbor" => Ok(output::cbor(&res)),
|
||||||
|
@ -210,7 +210,7 @@ async fn create_one(
|
||||||
id: String,
|
id: String,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
let db = DB.get().unwrap().clone();
|
let db = DB.get().unwrap();
|
||||||
let data = str::from_utf8(&body).unwrap();
|
let data = str::from_utf8(&body).unwrap();
|
||||||
match surrealdb::sql::json(data) {
|
match surrealdb::sql::json(data) {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
|
@ -220,7 +220,7 @@ async fn create_one(
|
||||||
String::from("id") => Value::from(id),
|
String::from("id") => Value::from(id),
|
||||||
String::from("data") => data,
|
String::from("data") => data,
|
||||||
};
|
};
|
||||||
match surrealdb::execute(db, sql, session, Some(vars)).await {
|
match db.execute(sql, &session, Some(vars)).await {
|
||||||
Ok(res) => match output.as_ref() {
|
Ok(res) => match output.as_ref() {
|
||||||
"application/json" => Ok(output::json(&res)),
|
"application/json" => Ok(output::json(&res)),
|
||||||
"application/cbor" => Ok(output::cbor(&res)),
|
"application/cbor" => Ok(output::cbor(&res)),
|
||||||
|
@ -241,7 +241,7 @@ async fn update_one(
|
||||||
id: String,
|
id: String,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
let db = DB.get().unwrap().clone();
|
let db = DB.get().unwrap();
|
||||||
let data = str::from_utf8(&body).unwrap();
|
let data = str::from_utf8(&body).unwrap();
|
||||||
match surrealdb::sql::json(data) {
|
match surrealdb::sql::json(data) {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
|
@ -251,7 +251,7 @@ async fn update_one(
|
||||||
String::from("id") => Value::from(id),
|
String::from("id") => Value::from(id),
|
||||||
String::from("data") => data,
|
String::from("data") => data,
|
||||||
};
|
};
|
||||||
match surrealdb::execute(db, sql, session, Some(vars)).await {
|
match db.execute(sql, &session, Some(vars)).await {
|
||||||
Ok(res) => match output.as_ref() {
|
Ok(res) => match output.as_ref() {
|
||||||
"application/json" => Ok(output::json(&res)),
|
"application/json" => Ok(output::json(&res)),
|
||||||
"application/cbor" => Ok(output::cbor(&res)),
|
"application/cbor" => Ok(output::cbor(&res)),
|
||||||
|
@ -272,7 +272,7 @@ async fn modify_one(
|
||||||
id: String,
|
id: String,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
let db = DB.get().unwrap().clone();
|
let db = DB.get().unwrap();
|
||||||
let data = str::from_utf8(&body).unwrap();
|
let data = str::from_utf8(&body).unwrap();
|
||||||
match surrealdb::sql::json(data) {
|
match surrealdb::sql::json(data) {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
|
@ -282,7 +282,7 @@ async fn modify_one(
|
||||||
String::from("id") => Value::from(id),
|
String::from("id") => Value::from(id),
|
||||||
String::from("data") => data,
|
String::from("data") => data,
|
||||||
};
|
};
|
||||||
match surrealdb::execute(db, sql, session, Some(vars)).await {
|
match db.execute(sql, &session, Some(vars)).await {
|
||||||
Ok(res) => match output.as_ref() {
|
Ok(res) => match output.as_ref() {
|
||||||
"application/json" => Ok(output::json(&res)),
|
"application/json" => Ok(output::json(&res)),
|
||||||
"application/cbor" => Ok(output::cbor(&res)),
|
"application/cbor" => Ok(output::cbor(&res)),
|
||||||
|
@ -302,13 +302,13 @@ async fn delete_one(
|
||||||
table: String,
|
table: String,
|
||||||
id: String,
|
id: String,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
let db = DB.get().unwrap().clone();
|
let db = DB.get().unwrap();
|
||||||
let sql = "DELETE type::thing($table, $id)";
|
let sql = "DELETE type::thing($table, $id)";
|
||||||
let vars = map! {
|
let vars = map! {
|
||||||
String::from("table") => Value::from(table),
|
String::from("table") => Value::from(table),
|
||||||
String::from("id") => Value::from(id),
|
String::from("id") => Value::from(id),
|
||||||
};
|
};
|
||||||
match surrealdb::execute(db, sql, session, Some(vars)).await {
|
match db.execute(sql, &session, Some(vars)).await {
|
||||||
Ok(res) => match output.as_ref() {
|
Ok(res) => match output.as_ref() {
|
||||||
"application/json" => Ok(output::json(&res)),
|
"application/json" => Ok(output::json(&res)),
|
||||||
"application/cbor" => Ok(output::cbor(&res)),
|
"application/cbor" => Ok(output::cbor(&res)),
|
||||||
|
|
|
@ -42,9 +42,9 @@ async fn handler(
|
||||||
output: String,
|
output: String,
|
||||||
sql: Bytes,
|
sql: Bytes,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
let db = DB.get().unwrap().clone();
|
let db = DB.get().unwrap();
|
||||||
let sql = std::str::from_utf8(&sql).unwrap();
|
let sql = std::str::from_utf8(&sql).unwrap();
|
||||||
match surrealdb::execute(db, sql, session, None).await {
|
match db.execute(sql, &session, None).await {
|
||||||
Ok(res) => match output.as_ref() {
|
Ok(res) => match output.as_ref() {
|
||||||
"application/json" => Ok(output::json(&res)),
|
"application/json" => Ok(output::json(&res)),
|
||||||
"application/cbor" => Ok(output::cbor(&res)),
|
"application/cbor" => Ok(output::cbor(&res)),
|
||||||
|
|
Loading…
Reference in a new issue