Enable new database strict mode configuration
This commit is contained in:
parent
f633769b57
commit
d619633340
15 changed files with 279 additions and 82 deletions
|
@ -35,6 +35,8 @@ pub struct Options {
|
||||||
pub events: bool,
|
pub events: bool,
|
||||||
// Should we process table queries?
|
// Should we process table queries?
|
||||||
pub tables: bool,
|
pub tables: bool,
|
||||||
|
// Should we error if tables don't exist?
|
||||||
|
pub strict: bool,
|
||||||
// Should we process function futures?
|
// Should we process function futures?
|
||||||
pub futures: bool,
|
pub futures: bool,
|
||||||
}
|
}
|
||||||
|
@ -59,6 +61,7 @@ impl Options {
|
||||||
fields: true,
|
fields: true,
|
||||||
events: true,
|
events: true,
|
||||||
tables: true,
|
tables: true,
|
||||||
|
strict: false,
|
||||||
futures: false,
|
futures: false,
|
||||||
auth: Arc::new(auth),
|
auth: Arc::new(auth),
|
||||||
}
|
}
|
||||||
|
@ -168,6 +171,17 @@ impl Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new Options object for a subquery
|
||||||
|
pub fn strict(&self, v: bool) -> Options {
|
||||||
|
Options {
|
||||||
|
auth: self.auth.clone(),
|
||||||
|
ns: self.ns.clone(),
|
||||||
|
db: self.db.clone(),
|
||||||
|
strict: v,
|
||||||
|
..*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new Options object for a subquery
|
// Create a new Options object for a subquery
|
||||||
pub fn futures(&self, v: bool) -> Options {
|
pub fn futures(&self, v: bool) -> Options {
|
||||||
Options {
|
Options {
|
||||||
|
@ -179,6 +193,7 @@ impl Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check whether realtime queries are supported
|
||||||
pub fn realtime(&self) -> Result<(), Error> {
|
pub fn realtime(&self) -> Result<(), Error> {
|
||||||
if !self.live {
|
if !self.live {
|
||||||
return Err(Error::RealtimeDisabled);
|
return Err(Error::RealtimeDisabled);
|
||||||
|
@ -194,7 +209,7 @@ impl Options {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether the authentication permissions are ok
|
// Check whether the necessary NS / DB options have been set
|
||||||
pub fn needs(&self, level: Level) -> Result<(), Error> {
|
pub fn needs(&self, level: Level) -> Result<(), Error> {
|
||||||
if self.ns.is_none() && matches!(level, Level::Ns | Level::Db) {
|
if self.ns.is_none() && matches!(level, Level::Ns | Level::Db) {
|
||||||
return Err(Error::NsEmpty);
|
return Err(Error::NsEmpty);
|
||||||
|
|
|
@ -50,21 +50,31 @@ impl<'a> Document<'a> {
|
||||||
opt: &Options,
|
opt: &Options,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
) -> Result<DefineTableStatement, Error> {
|
) -> Result<DefineTableStatement, Error> {
|
||||||
|
// Clone transaction
|
||||||
|
let run = txn.clone();
|
||||||
|
// Claim transaction
|
||||||
|
let mut run = run.lock().await;
|
||||||
// Get the record id
|
// Get the record id
|
||||||
let id = self.id.as_ref().unwrap();
|
let rid = self.id.as_ref().unwrap();
|
||||||
// Get the table definition
|
// Get the table definition
|
||||||
let tb = txn.clone().lock().await.get_tb(opt.ns(), opt.db(), &id.tb).await;
|
let tb = run.get_tb(opt.ns(), opt.db(), &rid.tb).await;
|
||||||
// Return the table or attempt to define it
|
// Return the table or attempt to define it
|
||||||
match tb {
|
match tb {
|
||||||
|
// The table doesn't exist
|
||||||
|
Err(Error::TbNotFound) => match opt.auth.check(Level::Db) {
|
||||||
|
// We can create the table automatically
|
||||||
|
true => {
|
||||||
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
|
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||||
|
run.add_tb(opt.ns(), opt.db(), &rid.tb, opt.strict).await
|
||||||
|
}
|
||||||
|
// We can't create the table so error
|
||||||
|
false => Err(Error::TbNotFound),
|
||||||
|
},
|
||||||
|
// There was an error
|
||||||
|
Err(err) => Err(err),
|
||||||
// The table exists
|
// The table exists
|
||||||
Ok(tb) => Ok(tb),
|
Ok(tb) => Ok(tb),
|
||||||
// The table doesn't exist
|
|
||||||
Err(e) => match opt.auth.check(Level::Db) {
|
|
||||||
// We can create the table automatically
|
|
||||||
true => txn.clone().lock().await.add_tb(opt.ns(), opt.db(), &id.tb).await,
|
|
||||||
// We can't create the table so error
|
|
||||||
false => Err(e),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get the foreign tables for this document
|
// Get the foreign tables for this document
|
||||||
|
|
|
@ -33,6 +33,10 @@ pub enum Error {
|
||||||
#[error("Value being checked was not correct")]
|
#[error("Value being checked was not correct")]
|
||||||
TxConditionNotMet,
|
TxConditionNotMet,
|
||||||
|
|
||||||
|
/// The key being inserted in the transaction already exists
|
||||||
|
#[error("The key being inserted already exists")]
|
||||||
|
TxKeyAlreadyExists,
|
||||||
|
|
||||||
/// No namespace has been selected
|
/// No namespace has been selected
|
||||||
#[error("Specify a namespace to use")]
|
#[error("Specify a namespace to use")]
|
||||||
NsEmpty,
|
NsEmpty,
|
||||||
|
@ -259,21 +263,30 @@ impl From<Error> for String {
|
||||||
#[cfg(feature = "kv-echodb")]
|
#[cfg(feature = "kv-echodb")]
|
||||||
impl From<echodb::err::Error> for Error {
|
impl From<echodb::err::Error> for Error {
|
||||||
fn from(e: echodb::err::Error) -> Error {
|
fn from(e: echodb::err::Error) -> Error {
|
||||||
Error::Tx(e.to_string())
|
match e {
|
||||||
|
echodb::err::Error::KeyAlreadyExists => Error::TxKeyAlreadyExists,
|
||||||
|
_ => Error::Tx(e.to_string()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "kv-indxdb")]
|
#[cfg(feature = "kv-indxdb")]
|
||||||
impl From<indxdb::err::Error> for Error {
|
impl From<indxdb::err::Error> for Error {
|
||||||
fn from(e: indxdb::err::Error) -> Error {
|
fn from(e: indxdb::err::Error) -> Error {
|
||||||
Error::Tx(e.to_string())
|
match e {
|
||||||
|
indxdb::err::Error::KeyAlreadyExists => Error::TxKeyAlreadyExists,
|
||||||
|
_ => Error::Tx(e.to_string()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "kv-tikv")]
|
#[cfg(feature = "kv-tikv")]
|
||||||
impl From<tikv::Error> for Error {
|
impl From<tikv::Error> for Error {
|
||||||
fn from(e: tikv::Error) -> Error {
|
fn from(e: tikv::Error) -> Error {
|
||||||
Error::Tx(e.to_string())
|
match e {
|
||||||
|
tikv::Error::DuplicateKeyInsertion => Error::TxKeyAlreadyExists,
|
||||||
|
_ => Error::Tx(e.to_string()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,7 @@ impl Datastore {
|
||||||
txt: &str,
|
txt: &str,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
vars: Variables,
|
vars: Variables,
|
||||||
|
strict: bool,
|
||||||
) -> Result<Vec<Response>, Error> {
|
) -> Result<Vec<Response>, Error> {
|
||||||
// Create a new query options
|
// Create a new query options
|
||||||
let mut opt = Options::default();
|
let mut opt = Options::default();
|
||||||
|
@ -179,6 +180,8 @@ impl Datastore {
|
||||||
// Set current NS and DB
|
// Set current NS and DB
|
||||||
opt.ns = sess.ns();
|
opt.ns = sess.ns();
|
||||||
opt.db = sess.db();
|
opt.db = sess.db();
|
||||||
|
// Set strict config
|
||||||
|
opt.strict = strict;
|
||||||
// Process all statements
|
// Process all statements
|
||||||
exe.execute(ctx, opt, ast).await
|
exe.execute(ctx, opt, ast).await
|
||||||
}
|
}
|
||||||
|
@ -189,6 +192,7 @@ impl Datastore {
|
||||||
ast: Query,
|
ast: Query,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
vars: Variables,
|
vars: Variables,
|
||||||
|
strict: bool,
|
||||||
) -> Result<Vec<Response>, Error> {
|
) -> Result<Vec<Response>, Error> {
|
||||||
// Create a new query options
|
// Create a new query options
|
||||||
let mut opt = Options::default();
|
let mut opt = Options::default();
|
||||||
|
@ -207,6 +211,8 @@ impl Datastore {
|
||||||
// Set current NS and DB
|
// Set current NS and DB
|
||||||
opt.ns = sess.ns();
|
opt.ns = sess.ns();
|
||||||
opt.db = sess.db();
|
opt.db = sess.db();
|
||||||
|
// Set strict config
|
||||||
|
opt.strict = strict;
|
||||||
// Process all statements
|
// Process all statements
|
||||||
exe.execute(ctx, opt, ast).await
|
exe.execute(ctx, opt, ast).await
|
||||||
}
|
}
|
||||||
|
@ -217,6 +223,7 @@ impl Datastore {
|
||||||
val: Value,
|
val: Value,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
vars: Variables,
|
vars: Variables,
|
||||||
|
strict: bool,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
// Start a new transaction
|
// Start a new transaction
|
||||||
let txn = self.transaction(val.writeable(), false).await?;
|
let txn = self.transaction(val.writeable(), false).await?;
|
||||||
|
@ -235,6 +242,8 @@ impl Datastore {
|
||||||
// Set current NS and DB
|
// Set current NS and DB
|
||||||
opt.ns = sess.ns();
|
opt.ns = sess.ns();
|
||||||
opt.db = sess.db();
|
opt.db = sess.db();
|
||||||
|
// Set strict config
|
||||||
|
opt.strict = strict;
|
||||||
// Compute the value
|
// Compute the value
|
||||||
let res = val.compute(&ctx, &opt, &txn, None).await?;
|
let res = val.compute(&ctx, &opt, &txn, None).await?;
|
||||||
// Store any data
|
// Store any data
|
||||||
|
|
|
@ -714,39 +714,76 @@ impl Transaction {
|
||||||
let val = self.get(key).await?.ok_or(Error::TbNotFound)?;
|
let val = self.get(key).await?.ok_or(Error::TbNotFound)?;
|
||||||
Ok(val.into())
|
Ok(val.into())
|
||||||
}
|
}
|
||||||
/// Add a namespace with a default configuration.
|
/// Add a namespace with a default configuration, only if we are in dynamic mode.
|
||||||
pub async fn add_ns(&mut self, ns: &str) -> Result<DefineNamespaceStatement, Error> {
|
pub async fn add_ns(
|
||||||
let key = crate::key::ns::new(ns);
|
&mut self,
|
||||||
let val = DefineNamespaceStatement {
|
ns: &str,
|
||||||
name: ns.to_owned().into(),
|
strict: bool,
|
||||||
};
|
) -> Result<DefineNamespaceStatement, Error> {
|
||||||
let _ = self.put(key, &val).await;
|
match self.get_ns(ns).await {
|
||||||
Ok(val)
|
Err(Error::NsNotFound) => match strict {
|
||||||
|
false => {
|
||||||
|
let key = crate::key::ns::new(ns);
|
||||||
|
let val = DefineNamespaceStatement {
|
||||||
|
name: ns.to_owned().into(),
|
||||||
|
};
|
||||||
|
self.put(key, &val).await?;
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
true => Err(Error::NsNotFound),
|
||||||
|
},
|
||||||
|
Err(e) => Err(e),
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Add a database with a default configuration.
|
/// Add a database with a default configuration, only if we are in dynamic mode.
|
||||||
pub async fn add_db(&mut self, ns: &str, db: &str) -> Result<DefineDatabaseStatement, Error> {
|
pub async fn add_db(
|
||||||
let key = crate::key::db::new(ns, db);
|
&mut self,
|
||||||
let val = DefineDatabaseStatement {
|
ns: &str,
|
||||||
name: db.to_owned().into(),
|
db: &str,
|
||||||
};
|
strict: bool,
|
||||||
let _ = self.put(key, &val).await;
|
) -> Result<DefineDatabaseStatement, Error> {
|
||||||
Ok(val)
|
match self.get_db(ns, db).await {
|
||||||
|
Err(Error::DbNotFound) => match strict {
|
||||||
|
false => {
|
||||||
|
let key = crate::key::db::new(ns, db);
|
||||||
|
let val = DefineDatabaseStatement {
|
||||||
|
name: db.to_owned().into(),
|
||||||
|
};
|
||||||
|
self.put(key, &val).await?;
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
true => Err(Error::DbNotFound),
|
||||||
|
},
|
||||||
|
Err(e) => Err(e),
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Add a table with a default configuration.
|
/// Add a table with a default configuration, only if we are in dynamic mode.
|
||||||
pub async fn add_tb(
|
pub async fn add_tb(
|
||||||
&mut self,
|
&mut self,
|
||||||
ns: &str,
|
ns: &str,
|
||||||
db: &str,
|
db: &str,
|
||||||
tb: &str,
|
tb: &str,
|
||||||
|
strict: bool,
|
||||||
) -> Result<DefineTableStatement, Error> {
|
) -> Result<DefineTableStatement, Error> {
|
||||||
let key = crate::key::tb::new(ns, db, tb);
|
match self.get_tb(ns, db, tb).await {
|
||||||
let val = DefineTableStatement {
|
Err(Error::TbNotFound) => match strict {
|
||||||
name: tb.to_owned().into(),
|
false => {
|
||||||
permissions: Permissions::none(),
|
let key = crate::key::tb::new(ns, db, tb);
|
||||||
..DefineTableStatement::default()
|
let val = DefineTableStatement {
|
||||||
};
|
name: tb.to_owned().into(),
|
||||||
let _ = self.put(key, &val).await;
|
permissions: Permissions::none(),
|
||||||
Ok(val)
|
..DefineTableStatement::default()
|
||||||
|
};
|
||||||
|
self.put(key, &val).await?;
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
true => Err(Error::TbNotFound),
|
||||||
|
},
|
||||||
|
Err(e) => Err(e),
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Writes the full database contents as binary SQL.
|
/// Writes the full database contents as binary SQL.
|
||||||
pub async fn export(&mut self, ns: &str, db: &str, chn: Sender<Vec<u8>>) -> Result<(), Error> {
|
pub async fn export(&mut self, ns: &str, db: &str, chn: Sender<Vec<u8>>) -> Result<(), Error> {
|
||||||
|
|
|
@ -173,7 +173,7 @@ impl DefineDatabaseStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let key = crate::key::db::new(opt.ns(), &self.name);
|
let key = crate::key::db::new(opt.ns(), &self.name);
|
||||||
run.add_ns(opt.ns()).await?;
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
run.set(key, self).await?;
|
run.set(key, self).await?;
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
|
@ -232,7 +232,7 @@ impl DefineLoginStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let key = crate::key::nl::new(opt.ns(), &self.name);
|
let key = crate::key::nl::new(opt.ns(), &self.name);
|
||||||
run.add_ns(opt.ns()).await?;
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
run.set(key, self).await?;
|
run.set(key, self).await?;
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
|
@ -248,8 +248,8 @@ impl DefineLoginStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let key = crate::key::dl::new(opt.ns(), opt.db(), &self.name);
|
let key = crate::key::dl::new(opt.ns(), opt.db(), &self.name);
|
||||||
run.add_ns(opt.ns()).await?;
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
run.add_db(opt.ns(), opt.db()).await?;
|
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||||
run.set(key, self).await?;
|
run.set(key, self).await?;
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
|
@ -361,7 +361,7 @@ impl DefineTokenStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let key = crate::key::nt::new(opt.ns(), &self.name);
|
let key = crate::key::nt::new(opt.ns(), &self.name);
|
||||||
run.add_ns(opt.ns()).await?;
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
run.set(key, self).await?;
|
run.set(key, self).await?;
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
|
@ -377,8 +377,8 @@ impl DefineTokenStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let key = crate::key::dt::new(opt.ns(), opt.db(), &self.name);
|
let key = crate::key::dt::new(opt.ns(), opt.db(), &self.name);
|
||||||
run.add_ns(opt.ns()).await?;
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
run.add_db(opt.ns(), opt.db()).await?;
|
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||||
run.set(key, self).await?;
|
run.set(key, self).await?;
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
|
@ -461,8 +461,8 @@ impl DefineScopeStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let key = crate::key::sc::new(opt.ns(), opt.db(), &self.name);
|
let key = crate::key::sc::new(opt.ns(), opt.db(), &self.name);
|
||||||
run.add_ns(opt.ns()).await?;
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
run.add_db(opt.ns(), opt.db()).await?;
|
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||||
run.set(key, self).await?;
|
run.set(key, self).await?;
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
|
@ -583,8 +583,8 @@ impl DefineTableStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let key = crate::key::tb::new(opt.ns(), opt.db(), &self.name);
|
let key = crate::key::tb::new(opt.ns(), opt.db(), &self.name);
|
||||||
run.add_ns(opt.ns()).await?;
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
run.add_db(opt.ns(), opt.db()).await?;
|
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||||
run.set(key, self).await?;
|
run.set(key, self).await?;
|
||||||
// Check if table is a view
|
// Check if table is a view
|
||||||
if let Some(view) = &self.view {
|
if let Some(view) = &self.view {
|
||||||
|
@ -752,9 +752,9 @@ impl DefineEventStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let key = crate::key::ev::new(opt.ns(), opt.db(), &self.what, &self.name);
|
let key = crate::key::ev::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||||
run.add_ns(opt.ns()).await?;
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
run.add_db(opt.ns(), opt.db()).await?;
|
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||||
run.add_tb(opt.ns(), opt.db(), &self.what).await?;
|
run.add_tb(opt.ns(), opt.db(), &self.what, opt.strict).await?;
|
||||||
run.set(key, self).await?;
|
run.set(key, self).await?;
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
|
@ -833,9 +833,9 @@ impl DefineFieldStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let key = crate::key::fd::new(opt.ns(), opt.db(), &self.what, &self.name.to_string());
|
let key = crate::key::fd::new(opt.ns(), opt.db(), &self.what, &self.name.to_string());
|
||||||
run.add_ns(opt.ns()).await?;
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
run.add_db(opt.ns(), opt.db()).await?;
|
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||||
run.add_tb(opt.ns(), opt.db(), &self.what).await?;
|
run.add_tb(opt.ns(), opt.db(), &self.what, opt.strict).await?;
|
||||||
run.set(key, self).await?;
|
run.set(key, self).await?;
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
|
@ -973,9 +973,9 @@ impl DefineIndexStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let key = crate::key::ix::new(opt.ns(), opt.db(), &self.what, &self.name);
|
let key = crate::key::ix::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||||
run.add_ns(opt.ns()).await?;
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
run.add_db(opt.ns(), opt.db()).await?;
|
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||||
run.add_tb(opt.ns(), opt.db(), &self.what).await?;
|
run.add_tb(opt.ns(), opt.db(), &self.what, opt.strict).await?;
|
||||||
run.set(key, self).await?;
|
run.set(key, self).await?;
|
||||||
// Remove the index data
|
// Remove the index data
|
||||||
let beg = crate::key::index::prefix(opt.ns(), opt.db(), &self.what, &self.name);
|
let beg = crate::key::index::prefix(opt.ns(), opt.db(), &self.what, &self.name);
|
||||||
|
|
|
@ -5,6 +5,7 @@ pub static CF: OnceCell<Config> = OnceCell::new();
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
pub strict: bool,
|
||||||
pub bind: SocketAddr,
|
pub bind: SocketAddr,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
pub user: String,
|
pub user: String,
|
||||||
|
@ -29,8 +30,11 @@ pub fn init(matches: &clap::ArgMatches) {
|
||||||
// Parse any TLS server security options
|
// Parse any TLS server security options
|
||||||
let crt = matches.value_of("web-crt").map(|v| v.to_owned());
|
let crt = matches.value_of("web-crt").map(|v| v.to_owned());
|
||||||
let key = matches.value_of("web-key").map(|v| v.to_owned());
|
let key = matches.value_of("web-key").map(|v| v.to_owned());
|
||||||
|
// Check if database strict mode is enabled
|
||||||
|
let strict = matches.is_present("strict");
|
||||||
// Store the new config object
|
// Store the new config object
|
||||||
let _ = CF.set(Config {
|
let _ = CF.set(Config {
|
||||||
|
strict,
|
||||||
bind,
|
bind,
|
||||||
path,
|
path,
|
||||||
user,
|
user,
|
||||||
|
|
|
@ -219,6 +219,14 @@ pub fn init() {
|
||||||
.forbid_empty_values(true)
|
.forbid_empty_values(true)
|
||||||
.help("Path to the private key file for encrypted client connections"),
|
.help("Path to the private key file for encrypted client connections"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("strict")
|
||||||
|
.short('s')
|
||||||
|
.long("strict")
|
||||||
|
.required(false)
|
||||||
|
.takes_value(false)
|
||||||
|
.help("Whether strict mode is enabled on this database instance"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("log")
|
Arg::new("log")
|
||||||
.short('l')
|
.short('l')
|
||||||
|
|
|
@ -5,9 +5,16 @@ use surrealdb::Datastore;
|
||||||
|
|
||||||
pub static DB: OnceCell<Datastore> = OnceCell::new();
|
pub static DB: OnceCell<Datastore> = OnceCell::new();
|
||||||
|
|
||||||
|
const LOG: &str = "surrealdb::dbs";
|
||||||
|
|
||||||
pub async fn init() -> Result<(), Error> {
|
pub async fn init() -> Result<(), Error> {
|
||||||
// Get local copy of options
|
// Get local copy of options
|
||||||
let opt = CF.get().unwrap();
|
let opt = CF.get().unwrap();
|
||||||
|
// Log authentication options
|
||||||
|
match opt.strict {
|
||||||
|
true => info!(target: LOG, "Database strict mode is enabled"),
|
||||||
|
false => info!(target: LOG, "Database strict mode is disabled"),
|
||||||
|
};
|
||||||
// Parse and setup the desired kv datastore
|
// Parse and setup the desired kv datastore
|
||||||
let dbs = Datastore::new(&opt.path).await?;
|
let dbs = Datastore::new(&opt.path).await?;
|
||||||
// Store database instance
|
// Store database instance
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::cli::CF;
|
||||||
use crate::cnf::SERVER_NAME;
|
use crate::cnf::SERVER_NAME;
|
||||||
use crate::dbs::DB;
|
use crate::dbs::DB;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
@ -76,6 +77,8 @@ pub async fn signin(vars: Object) -> Result<String, Error> {
|
||||||
pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<String, Error> {
|
pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<String, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Create a new readonly transaction
|
// Create a new readonly transaction
|
||||||
let mut tx = kvs.transaction(false, false).await?;
|
let mut tx = kvs.transaction(false, false).await?;
|
||||||
// Check if the supplied NS Login exists
|
// Check if the supplied NS Login exists
|
||||||
|
@ -89,7 +92,7 @@ pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<Stri
|
||||||
// Setup the query session
|
// Setup the query session
|
||||||
let sess = Session::for_db(&ns, &db);
|
let sess = Session::for_db(&ns, &db);
|
||||||
// Compute the value with the params
|
// Compute the value with the params
|
||||||
match kvs.compute(val, &sess, vars).await {
|
match kvs.compute(val, &sess, vars, opt.strict).await {
|
||||||
// The signin value succeeded
|
// The signin value succeeded
|
||||||
Ok(val) => match val.rid() {
|
Ok(val) => match val.rid() {
|
||||||
// There is a record returned
|
// There is a record returned
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::cli::CF;
|
||||||
use crate::cnf::SERVER_NAME;
|
use crate::cnf::SERVER_NAME;
|
||||||
use crate::dbs::DB;
|
use crate::dbs::DB;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
@ -31,6 +32,8 @@ pub async fn signup(vars: Object) -> Result<String, Error> {
|
||||||
pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<String, Error> {
|
pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<String, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Create a new readonly transaction
|
// Create a new readonly transaction
|
||||||
let mut tx = kvs.transaction(false, false).await?;
|
let mut tx = kvs.transaction(false, false).await?;
|
||||||
// Check if the supplied NS Login exists
|
// Check if the supplied NS Login exists
|
||||||
|
@ -44,7 +47,7 @@ pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<Stri
|
||||||
// Setup the query session
|
// Setup the query session
|
||||||
let sess = Session::for_db(&ns, &db);
|
let sess = Session::for_db(&ns, &db);
|
||||||
// Compute the value with the params
|
// Compute the value with the params
|
||||||
match kvs.compute(val, &sess, vars).await {
|
match kvs.compute(val, &sess, vars, opt.strict).await {
|
||||||
// The signin value succeeded
|
// The signin value succeeded
|
||||||
Ok(val) => match val.rid() {
|
Ok(val) => match val.rid() {
|
||||||
// There is a record returned
|
// There is a record returned
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::cli::CF;
|
||||||
use crate::dbs::DB;
|
use crate::dbs::DB;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::net::output;
|
use crate::net::output;
|
||||||
|
@ -30,10 +31,12 @@ async fn handler(
|
||||||
true => {
|
true => {
|
||||||
// Get the datastore reference
|
// Get the datastore reference
|
||||||
let db = DB.get().unwrap();
|
let db = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Convert the body to a byte slice
|
// Convert the body to a byte slice
|
||||||
let sql = std::str::from_utf8(&sql).unwrap();
|
let sql = std::str::from_utf8(&sql).unwrap();
|
||||||
// Execute the sql query in the database
|
// Execute the sql query in the database
|
||||||
match db.execute(sql, &session, None).await {
|
match db.execute(sql, &session, None, opt.strict).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)),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::cli::CF;
|
||||||
use crate::dbs::DB;
|
use crate::dbs::DB;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::net::output;
|
use crate::net::output;
|
||||||
|
@ -124,16 +125,22 @@ async fn select_all(
|
||||||
table: String,
|
table: String,
|
||||||
query: Query,
|
query: Query,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
|
// Get the datastore reference
|
||||||
let db = DB.get().unwrap();
|
let db = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
|
// Specify the request statement
|
||||||
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")),
|
||||||
s = query.start.unwrap_or_else(|| String::from("0")),
|
s = query.start.unwrap_or_else(|| String::from("0")),
|
||||||
);
|
);
|
||||||
|
// Specify the request variables
|
||||||
let vars = map! {
|
let vars = map! {
|
||||||
String::from("table") => Value::from(table),
|
String::from("table") => Value::from(table),
|
||||||
};
|
};
|
||||||
match db.execute(sql.as_str(), &session, Some(vars)).await {
|
// Execute the query and return the result
|
||||||
|
match db.execute(sql.as_str(), &session, Some(vars), opt.strict).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)),
|
||||||
|
@ -150,16 +157,24 @@ async fn create_all(
|
||||||
table: String,
|
table: String,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
|
// Get the datastore reference
|
||||||
let db = DB.get().unwrap();
|
let db = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
|
// Convert the HTTP request body
|
||||||
let data = str::from_utf8(&body).unwrap();
|
let data = str::from_utf8(&body).unwrap();
|
||||||
|
// Parse the request body as JSON
|
||||||
match surrealdb::sql::json(data) {
|
match surrealdb::sql::json(data) {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
|
// Specify the request statement
|
||||||
let sql = "CREATE type::table($table) CONTENT $data";
|
let sql = "CREATE type::table($table) CONTENT $data";
|
||||||
|
// Specify the request variables
|
||||||
let vars = map! {
|
let vars = map! {
|
||||||
String::from("table") => Value::from(table),
|
String::from("table") => Value::from(table),
|
||||||
String::from("data") => data,
|
String::from("data") => data,
|
||||||
};
|
};
|
||||||
match db.execute(sql, &session, Some(vars)).await {
|
// Execute the query and return the result
|
||||||
|
match db.execute(sql, &session, Some(vars), opt.strict).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)),
|
||||||
|
@ -178,12 +193,18 @@ async fn delete_all(
|
||||||
output: String,
|
output: String,
|
||||||
table: String,
|
table: String,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
|
// Get the datastore reference
|
||||||
let db = DB.get().unwrap();
|
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)";
|
let sql = "DELETE type::table($table)";
|
||||||
|
// Specify the request variables
|
||||||
let vars = map! {
|
let vars = map! {
|
||||||
String::from("table") => Value::from(table),
|
String::from("table") => Value::from(table),
|
||||||
};
|
};
|
||||||
match db.execute(sql, &session, Some(vars)).await {
|
// Execute the query and return the result
|
||||||
|
match db.execute(sql, &session, Some(vars), opt.strict).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)),
|
||||||
|
@ -204,13 +225,19 @@ async fn select_one(
|
||||||
table: String,
|
table: String,
|
||||||
id: String,
|
id: String,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
|
// Get the datastore reference
|
||||||
let db = DB.get().unwrap();
|
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)";
|
let sql = "SELECT * FROM type::thing($table, $id)";
|
||||||
|
// Specify the request variables
|
||||||
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 db.execute(sql, &session, Some(vars)).await {
|
// Execute the query and return the result
|
||||||
|
match db.execute(sql, &session, Some(vars), opt.strict).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)),
|
||||||
|
@ -228,17 +255,25 @@ async fn create_one(
|
||||||
id: String,
|
id: String,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
|
// Get the datastore reference
|
||||||
let db = DB.get().unwrap();
|
let db = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
|
// Convert the HTTP request body
|
||||||
let data = str::from_utf8(&body).unwrap();
|
let data = str::from_utf8(&body).unwrap();
|
||||||
|
// Parse the request body as JSON
|
||||||
match surrealdb::sql::json(data) {
|
match surrealdb::sql::json(data) {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
|
// Specify the request statement
|
||||||
let sql = "CREATE type::thing($table, $id) CONTENT $data";
|
let sql = "CREATE type::thing($table, $id) CONTENT $data";
|
||||||
|
// Specify the request variables
|
||||||
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),
|
||||||
String::from("data") => data,
|
String::from("data") => data,
|
||||||
};
|
};
|
||||||
match db.execute(sql, &session, Some(vars)).await {
|
// Execute the query and return the result
|
||||||
|
match db.execute(sql, &session, Some(vars), opt.strict).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)),
|
||||||
|
@ -259,17 +294,25 @@ async fn update_one(
|
||||||
id: String,
|
id: String,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
|
// Get the datastore reference
|
||||||
let db = DB.get().unwrap();
|
let db = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
|
// Convert the HTTP request body
|
||||||
let data = str::from_utf8(&body).unwrap();
|
let data = str::from_utf8(&body).unwrap();
|
||||||
|
// Parse the request body as JSON
|
||||||
match surrealdb::sql::json(data) {
|
match surrealdb::sql::json(data) {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
|
// Specify the request statement
|
||||||
let sql = "UPDATE type::thing($table, $id) CONTENT $data";
|
let sql = "UPDATE type::thing($table, $id) CONTENT $data";
|
||||||
|
// Specify the request variables
|
||||||
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),
|
||||||
String::from("data") => data,
|
String::from("data") => data,
|
||||||
};
|
};
|
||||||
match db.execute(sql, &session, Some(vars)).await {
|
// Execute the query and return the result
|
||||||
|
match db.execute(sql, &session, Some(vars), opt.strict).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)),
|
||||||
|
@ -290,17 +333,25 @@ async fn modify_one(
|
||||||
id: String,
|
id: String,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
|
// Get the datastore reference
|
||||||
let db = DB.get().unwrap();
|
let db = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
|
// Convert the HTTP request body
|
||||||
let data = str::from_utf8(&body).unwrap();
|
let data = str::from_utf8(&body).unwrap();
|
||||||
|
// Parse the request body as JSON
|
||||||
match surrealdb::sql::json(data) {
|
match surrealdb::sql::json(data) {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
|
// Specify the request statement
|
||||||
let sql = "UPDATE type::thing($table, $id) MERGE $data";
|
let sql = "UPDATE type::thing($table, $id) MERGE $data";
|
||||||
|
// Specify the request variables
|
||||||
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),
|
||||||
String::from("data") => data,
|
String::from("data") => data,
|
||||||
};
|
};
|
||||||
match db.execute(sql, &session, Some(vars)).await {
|
// Execute the query and return the result
|
||||||
|
match db.execute(sql, &session, Some(vars), opt.strict).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)),
|
||||||
|
@ -320,13 +371,19 @@ async fn delete_one(
|
||||||
table: String,
|
table: String,
|
||||||
id: String,
|
id: String,
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
|
// Get the datastore reference
|
||||||
let db = DB.get().unwrap();
|
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)";
|
let sql = "DELETE type::thing($table, $id)";
|
||||||
|
// Specify the request variables
|
||||||
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 db.execute(sql, &session, Some(vars)).await {
|
// Execute the query and return the result
|
||||||
|
match db.execute(sql, &session, Some(vars), opt.strict).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)),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::cli::CF;
|
||||||
use crate::cnf::MAX_CONCURRENT_CALLS;
|
use crate::cnf::MAX_CONCURRENT_CALLS;
|
||||||
use crate::dbs::DB;
|
use crate::dbs::DB;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
@ -232,10 +233,12 @@ impl Rpc {
|
||||||
async fn info(&self) -> Result<Value, Error> {
|
async fn info(&self) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the SQL query string
|
// Specify the SQL query string
|
||||||
let sql = "SELECT * FROM $auth";
|
let sql = "SELECT * FROM $auth";
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let mut res = kvs.execute(sql, &self.session, None).await?;
|
let mut res = kvs.execute(sql, &self.session, None, opt.strict).await?;
|
||||||
// Extract the first value from the result
|
// Extract the first value from the result
|
||||||
let res = res.remove(0).result?.first();
|
let res = res.remove(0).result?.first();
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
@ -268,6 +271,8 @@ impl Rpc {
|
||||||
async fn kill(&self, id: Value) -> Result<Value, Error> {
|
async fn kill(&self, id: Value) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the SQL query string
|
// Specify the SQL query string
|
||||||
let sql = "KILL $id";
|
let sql = "KILL $id";
|
||||||
// Specify the query paramaters
|
// Specify the query paramaters
|
||||||
|
@ -276,7 +281,7 @@ impl Rpc {
|
||||||
=> &self.vars
|
=> &self.vars
|
||||||
});
|
});
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = res.remove(0).result?;
|
let res = res.remove(0).result?;
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
@ -286,6 +291,8 @@ impl Rpc {
|
||||||
async fn live(&self, tb: Value) -> Result<Value, Error> {
|
async fn live(&self, tb: Value) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the SQL query string
|
// Specify the SQL query string
|
||||||
let sql = "LIVE SELECT * FROM $tb";
|
let sql = "LIVE SELECT * FROM $tb";
|
||||||
// Specify the query paramaters
|
// Specify the query paramaters
|
||||||
|
@ -294,7 +301,7 @@ impl Rpc {
|
||||||
=> &self.vars
|
=> &self.vars
|
||||||
});
|
});
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = res.remove(0).result?;
|
let res = res.remove(0).result?;
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
@ -308,10 +315,12 @@ impl Rpc {
|
||||||
async fn query(&self, sql: Strand) -> Result<Value, Error> {
|
async fn query(&self, sql: Strand) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the query paramaters
|
// Specify the query paramaters
|
||||||
let var = Some(self.vars.clone());
|
let var = Some(self.vars.clone());
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let res = kvs.execute(&sql, &self.session, var).await?;
|
let res = kvs.execute(&sql, &self.session, var, opt.strict).await?;
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = res.into_iter().collect::<Vec<Value>>().into();
|
let res = res.into_iter().collect::<Vec<Value>>().into();
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
@ -321,10 +330,12 @@ impl Rpc {
|
||||||
async fn query_with(&self, sql: Strand, mut vars: Object) -> Result<Value, Error> {
|
async fn query_with(&self, sql: Strand, mut vars: Object) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the query paramaters
|
// Specify the query paramaters
|
||||||
let var = Some(mrg! { vars.0, &self.vars });
|
let var = Some(mrg! { vars.0, &self.vars });
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let res = kvs.execute(&sql, &self.session, var).await?;
|
let res = kvs.execute(&sql, &self.session, var, opt.strict).await?;
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = res.into_iter().collect::<Vec<Value>>().into();
|
let res = res.into_iter().collect::<Vec<Value>>().into();
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
@ -338,6 +349,8 @@ impl Rpc {
|
||||||
async fn select(&self, what: Value) -> Result<Value, Error> {
|
async fn select(&self, what: Value) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the SQL query string
|
// Specify the SQL query string
|
||||||
let sql = "SELECT * FROM $what";
|
let sql = "SELECT * FROM $what";
|
||||||
// Specify the query paramaters
|
// Specify the query paramaters
|
||||||
|
@ -346,7 +359,7 @@ impl Rpc {
|
||||||
=> &self.vars
|
=> &self.vars
|
||||||
});
|
});
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = res.remove(0).result?;
|
let res = res.remove(0).result?;
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
@ -360,6 +373,8 @@ impl Rpc {
|
||||||
async fn create(&self, what: Value, data: impl Into<Option<Value>>) -> Result<Value, Error> {
|
async fn create(&self, what: Value, data: impl Into<Option<Value>>) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the SQL query string
|
// Specify the SQL query string
|
||||||
let sql = "CREATE $what CONTENT $data RETURN AFTER";
|
let sql = "CREATE $what CONTENT $data RETURN AFTER";
|
||||||
// Specify the query paramaters
|
// Specify the query paramaters
|
||||||
|
@ -369,7 +384,7 @@ impl Rpc {
|
||||||
=> &self.vars
|
=> &self.vars
|
||||||
});
|
});
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = res.remove(0).result?;
|
let res = res.remove(0).result?;
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
@ -383,6 +398,8 @@ impl Rpc {
|
||||||
async fn update(&self, what: Value, data: impl Into<Option<Value>>) -> Result<Value, Error> {
|
async fn update(&self, what: Value, data: impl Into<Option<Value>>) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the SQL query string
|
// Specify the SQL query string
|
||||||
let sql = "UPDATE $what CONTENT $data RETURN AFTER";
|
let sql = "UPDATE $what CONTENT $data RETURN AFTER";
|
||||||
// Specify the query paramaters
|
// Specify the query paramaters
|
||||||
|
@ -392,7 +409,7 @@ impl Rpc {
|
||||||
=> &self.vars
|
=> &self.vars
|
||||||
});
|
});
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = res.remove(0).result?;
|
let res = res.remove(0).result?;
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
@ -406,6 +423,8 @@ impl Rpc {
|
||||||
async fn change(&self, what: Value, data: impl Into<Option<Value>>) -> Result<Value, Error> {
|
async fn change(&self, what: Value, data: impl Into<Option<Value>>) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the SQL query string
|
// Specify the SQL query string
|
||||||
let sql = "UPDATE $what MERGE $data RETURN AFTER";
|
let sql = "UPDATE $what MERGE $data RETURN AFTER";
|
||||||
// Specify the query paramaters
|
// Specify the query paramaters
|
||||||
|
@ -415,7 +434,7 @@ impl Rpc {
|
||||||
=> &self.vars
|
=> &self.vars
|
||||||
});
|
});
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = res.remove(0).result?;
|
let res = res.remove(0).result?;
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
@ -429,6 +448,8 @@ impl Rpc {
|
||||||
async fn modify(&self, what: Value, data: impl Into<Option<Value>>) -> Result<Value, Error> {
|
async fn modify(&self, what: Value, data: impl Into<Option<Value>>) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the SQL query string
|
// Specify the SQL query string
|
||||||
let sql = "UPDATE $what PATCH $data RETURN DIFF";
|
let sql = "UPDATE $what PATCH $data RETURN DIFF";
|
||||||
// Specify the query paramaters
|
// Specify the query paramaters
|
||||||
|
@ -438,7 +459,7 @@ impl Rpc {
|
||||||
=> &self.vars
|
=> &self.vars
|
||||||
});
|
});
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = res.remove(0).result?;
|
let res = res.remove(0).result?;
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
@ -452,6 +473,8 @@ impl Rpc {
|
||||||
async fn delete(&self, what: Value) -> Result<Value, Error> {
|
async fn delete(&self, what: Value) -> Result<Value, Error> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Specify the SQL query string
|
// Specify the SQL query string
|
||||||
let sql = "DELETE $what";
|
let sql = "DELETE $what";
|
||||||
// Specify the query paramaters
|
// Specify the query paramaters
|
||||||
|
@ -460,7 +483,7 @@ impl Rpc {
|
||||||
=> &self.vars
|
=> &self.vars
|
||||||
});
|
});
|
||||||
// Execute the query on the database
|
// Execute the query on the database
|
||||||
let mut res = kvs.execute(sql, &self.session, var).await?;
|
let mut res = kvs.execute(sql, &self.session, var, opt.strict).await?;
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = res.remove(0).result?;
|
let res = res.remove(0).result?;
|
||||||
// Return the result to the client
|
// Return the result to the client
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::cli::CF;
|
||||||
use crate::dbs::DB;
|
use crate::dbs::DB;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::net::output;
|
use crate::net::output;
|
||||||
|
@ -39,10 +40,12 @@ async fn handler(
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let db = DB.get().unwrap();
|
let db = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Convert the received sql query
|
// Convert the received sql query
|
||||||
let sql = std::str::from_utf8(&sql).unwrap();
|
let sql = std::str::from_utf8(&sql).unwrap();
|
||||||
// Execute the received sql query
|
// Execute the received sql query
|
||||||
match db.execute(sql, &session, None).await {
|
match db.execute(sql, &session, None, opt.strict).await {
|
||||||
// Convert the response to JSON
|
// Convert the response to JSON
|
||||||
Ok(res) => match output.as_ref() {
|
Ok(res) => match output.as_ref() {
|
||||||
"application/json" => Ok(output::json(&res)),
|
"application/json" => Ok(output::json(&res)),
|
||||||
|
@ -65,8 +68,10 @@ async fn socket(ws: WebSocket, session: Session) {
|
||||||
if let Ok(sql) = msg.to_str() {
|
if let Ok(sql) = msg.to_str() {
|
||||||
// Get a database reference
|
// Get a database reference
|
||||||
let db = DB.get().unwrap();
|
let db = DB.get().unwrap();
|
||||||
|
// Get local copy of options
|
||||||
|
let opt = CF.get().unwrap();
|
||||||
// Execute the received sql query
|
// Execute the received sql query
|
||||||
let _ = match db.execute(sql, &session, None).await {
|
let _ = match db.execute(sql, &session, None, opt.strict).await {
|
||||||
// Convert the response to JSON
|
// Convert the response to JSON
|
||||||
Ok(v) => match serde_json::to_string(&v) {
|
Ok(v) => match serde_json::to_string(&v) {
|
||||||
// Send the JSON response to the client
|
// Send the JSON response to the client
|
||||||
|
|
Loading…
Reference in a new issue