Implement IF EXISTS
for additional REMOVE
-statements (#3377)
Co-authored-by: Tobie Morgan Hitchcock <tobie@surrealdb.com> Co-authored-by: Rushmore Mushambi <rushmore@surrealdb.com>
This commit is contained in:
parent
0e2f83ed9d
commit
50b4b07b38
32 changed files with 1632 additions and 338 deletions
|
@ -319,12 +319,26 @@ pub enum Error {
|
|||
value: String,
|
||||
},
|
||||
|
||||
/// The requested event does not exist
|
||||
#[error("The event '{value}' does not exist")]
|
||||
#[cfg(feature = "sql2")]
|
||||
EvNotFound {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested function does not exist
|
||||
#[error("The function 'fn::{value}' does not exist")]
|
||||
FcNotFound {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested field does not exist
|
||||
#[error("The field '{value}' does not exist")]
|
||||
#[cfg(feature = "sql2")]
|
||||
FdNotFound {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested model does not exist
|
||||
#[error("The model 'ml::{value}' does not exist")]
|
||||
MlNotFound {
|
||||
|
|
|
@ -1908,6 +1908,36 @@ impl Transaction {
|
|||
Ok(val.into())
|
||||
}
|
||||
|
||||
/// Retrieve a specific function definition from a database.
|
||||
#[cfg(feature = "sql2")]
|
||||
pub async fn get_db_function(
|
||||
&mut self,
|
||||
ns: &str,
|
||||
db: &str,
|
||||
fc: &str,
|
||||
) -> Result<DefineFunctionStatement, Error> {
|
||||
let key = crate::key::database::fc::new(ns, db, fc);
|
||||
let val = self.get(key).await?.ok_or(Error::FcNotFound {
|
||||
value: fc.to_owned(),
|
||||
})?;
|
||||
Ok(val.into())
|
||||
}
|
||||
|
||||
/// Retrieve a specific function definition from a database.
|
||||
#[cfg(feature = "sql2")]
|
||||
pub async fn get_db_param(
|
||||
&mut self,
|
||||
ns: &str,
|
||||
db: &str,
|
||||
pa: &str,
|
||||
) -> Result<DefineParamStatement, Error> {
|
||||
let key = crate::key::database::pa::new(ns, db, pa);
|
||||
let val = self.get(key).await?.ok_or(Error::PaNotFound {
|
||||
value: pa.to_owned(),
|
||||
})?;
|
||||
Ok(val.into())
|
||||
}
|
||||
|
||||
/// Retrieve a specific scope definition.
|
||||
pub async fn get_sc(
|
||||
&mut self,
|
||||
|
@ -1983,6 +2013,60 @@ impl Transaction {
|
|||
Ok(val.into())
|
||||
}
|
||||
|
||||
/// Retrieve an event for a table.
|
||||
#[cfg(feature = "sql2")]
|
||||
pub async fn get_tb_event(
|
||||
&mut self,
|
||||
ns: &str,
|
||||
db: &str,
|
||||
tb: &str,
|
||||
ev: &str,
|
||||
) -> Result<DefineEventStatement, Error> {
|
||||
let key = crate::key::table::ev::new(ns, db, tb, ev);
|
||||
let key_enc = crate::key::table::ev::Ev::encode(&key)?;
|
||||
trace!("Getting ev ({:?}) {:?}", ev, crate::key::debug::sprint_key(&key_enc));
|
||||
let val = self.get(key_enc).await?.ok_or(Error::EvNotFound {
|
||||
value: ev.to_string(),
|
||||
})?;
|
||||
Ok(val.into())
|
||||
}
|
||||
|
||||
/// Retrieve an event for a table.
|
||||
#[cfg(feature = "sql2")]
|
||||
pub async fn get_tb_field(
|
||||
&mut self,
|
||||
ns: &str,
|
||||
db: &str,
|
||||
tb: &str,
|
||||
fd: &str,
|
||||
) -> Result<DefineFieldStatement, Error> {
|
||||
let key = crate::key::table::fd::new(ns, db, tb, fd);
|
||||
let key_enc = crate::key::table::fd::Fd::encode(&key)?;
|
||||
trace!("Getting fd ({:?}) {:?}", fd, crate::key::debug::sprint_key(&key_enc));
|
||||
let val = self.get(key_enc).await?.ok_or(Error::FdNotFound {
|
||||
value: fd.to_string(),
|
||||
})?;
|
||||
Ok(val.into())
|
||||
}
|
||||
|
||||
/// Retrieve an event for a table.
|
||||
#[cfg(feature = "sql2")]
|
||||
pub async fn get_tb_index(
|
||||
&mut self,
|
||||
ns: &str,
|
||||
db: &str,
|
||||
tb: &str,
|
||||
ix: &str,
|
||||
) -> Result<DefineFieldStatement, Error> {
|
||||
let key = crate::key::table::ix::new(ns, db, tb, ix);
|
||||
let key_enc = crate::key::table::ix::Ix::encode(&key)?;
|
||||
trace!("Getting ix ({:?}) {:?}", ix, crate::key::debug::sprint_key(&key_enc));
|
||||
let val = self.get(key_enc).await?.ok_or(Error::IxNotFound {
|
||||
value: ix.to_string(),
|
||||
})?;
|
||||
Ok(val.into())
|
||||
}
|
||||
|
||||
/// Add a namespace with a default configuration, only if we are in dynamic mode.
|
||||
pub async fn add_ns(
|
||||
&mut self,
|
||||
|
|
|
@ -39,6 +39,6 @@ impl RemoveParamStatement {
|
|||
|
||||
impl Display for RemoveParamStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE PARAM {}", self.name)
|
||||
write!(f, "REMOVE PARAM ${}", self.name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ use std::fmt::{self, Display, Formatter};
|
|||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
pub struct RemoveAnalyzerStatement {
|
||||
pub name: Ident,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveAnalyzerStatement {
|
||||
|
@ -22,23 +24,39 @@ impl RemoveAnalyzerStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Analyzer, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::database::az::new(opt.ns(), opt.db(), &self.name);
|
||||
run.del(key).await?;
|
||||
// TODO Check that the analyzer is not used in any schema
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Analyzer, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let az = run.get_db_analyzer(opt.ns(), opt.db(), &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::database::az::new(opt.ns(), opt.db(), &az.name);
|
||||
run.del(key).await?;
|
||||
// TODO Check that the analyzer is not used in any schema
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::AzNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveAnalyzerStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE ANALYZER {}", self.name)
|
||||
write!(f, "REMOVE ANALYZER")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " {}", self.name)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ use std::fmt::{self, Display, Formatter};
|
|||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
pub struct RemoveDatabaseStatement {
|
||||
pub name: Ident,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveDatabaseStatement {
|
||||
|
@ -23,25 +25,41 @@ impl RemoveDatabaseStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Database, &Base::Ns)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::namespace::db::new(opt.ns(), &self.name);
|
||||
run.del(key).await?;
|
||||
// Delete the resource data
|
||||
let key = crate::key::database::all::new(opt.ns(), &self.name);
|
||||
run.delp(key, u32::MAX).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Database, &Base::Ns)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let db = run.get_db(opt.ns(), &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::namespace::db::new(opt.ns(), &db.name);
|
||||
run.del(key).await?;
|
||||
// Delete the resource data
|
||||
let key = crate::key::database::all::new(opt.ns(), &db.name);
|
||||
run.delp(key, u32::MAX).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::DbNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveDatabaseStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE DATABASE {}", self.name)
|
||||
write!(f, "REMOVE DATABASE")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " {}", self.name)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,12 @@ use std::fmt::{self, Display, Formatter};
|
|||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
pub struct RemoveEventStatement {
|
||||
pub name: Ident,
|
||||
pub what: Ident,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveEventStatement {
|
||||
|
@ -24,25 +26,41 @@ impl RemoveEventStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Event, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::table::ev::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||
run.del(key).await?;
|
||||
// Clear the cache
|
||||
let key = crate::key::table::ev::prefix(opt.ns(), opt.db(), &self.what);
|
||||
run.clr(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Event, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let ev = run.get_tb_event(opt.ns(), opt.db(), &self.what, &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::table::ev::new(opt.ns(), opt.db(), &ev.what, &ev.name);
|
||||
run.del(key).await?;
|
||||
// Clear the cache
|
||||
let key = crate::key::table::ev::prefix(opt.ns(), opt.db(), &ev.what);
|
||||
run.clr(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::EvNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveEventStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE EVENT {} ON {}", self.name, self.what)
|
||||
write!(f, "REMOVE EVENT")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " {} ON {}", self.name, self.what)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,13 @@ use serde::{Deserialize, Serialize};
|
|||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
pub struct RemoveFieldStatement {
|
||||
pub name: Idiom,
|
||||
pub what: Ident,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveFieldStatement {
|
||||
|
@ -24,26 +26,43 @@ impl RemoveFieldStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Field, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let fd = self.name.to_string();
|
||||
let key = crate::key::table::fd::new(opt.ns(), opt.db(), &self.what, &fd);
|
||||
run.del(key).await?;
|
||||
// Clear the cache
|
||||
let key = crate::key::table::fd::prefix(opt.ns(), opt.db(), &self.what);
|
||||
run.clr(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Field, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let fd_name = self.name.to_string();
|
||||
let fd = run.get_tb_field(opt.ns(), opt.db(), &self.what, &fd_name).await?;
|
||||
// Delete the definition
|
||||
let fd_name = fd.name.to_string();
|
||||
let key = crate::key::table::fd::new(opt.ns(), opt.db(), &self.what, &fd_name);
|
||||
run.del(key).await?;
|
||||
// Clear the cache
|
||||
let key = crate::key::table::fd::prefix(opt.ns(), opt.db(), &self.what);
|
||||
run.clr(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::FdNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveFieldStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE FIELD {} ON {}", self.name, self.what)
|
||||
write!(f, "REMOVE FIELD")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " {} ON {}", self.name, self.what)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ use std::fmt::{self, Display};
|
|||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
pub struct RemoveFunctionStatement {
|
||||
pub name: Ident,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveFunctionStatement {
|
||||
|
@ -23,23 +25,39 @@ impl RemoveFunctionStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Function, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::database::fc::new(opt.ns(), opt.db(), &self.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Function, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let fc = run.get_db_function(opt.ns(), opt.db(), &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::database::fc::new(opt.ns(), opt.db(), &fc.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::FcNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveFunctionStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// Bypass ident display since we don't want backticks arround the ident.
|
||||
write!(f, "REMOVE FUNCTION fn::{}", self.name.0)
|
||||
write!(f, "REMOVE FUNCTION")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " fn::{}", self.name.0)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,13 @@ use serde::{Deserialize, Serialize};
|
|||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
pub struct RemoveIndexStatement {
|
||||
pub name: Ident,
|
||||
pub what: Ident,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveIndexStatement {
|
||||
|
@ -24,30 +26,44 @@ impl RemoveIndexStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Index, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the index store cache
|
||||
ctx.get_index_stores().index_removed(opt, &mut run, &self.what, &self.name).await?;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::table::ix::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||
run.del(key).await?;
|
||||
// Remove the index data
|
||||
let key = crate::key::index::all::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||
run.delp(key, u32::MAX).await?;
|
||||
// Clear the cache
|
||||
let key = crate::key::table::ix::prefix(opt.ns(), opt.db(), &self.what);
|
||||
run.clr(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Index, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the index store cache
|
||||
ctx.get_index_stores().index_removed(opt, &mut run, &self.what, &self.name).await?;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::table::ix::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||
run.del(key).await?;
|
||||
// Remove the index data
|
||||
let key = crate::key::index::all::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||
run.delp(key, u32::MAX).await?;
|
||||
// Clear the cache
|
||||
let key = crate::key::table::ix::prefix(opt.ns(), opt.db(), &self.what);
|
||||
run.clr(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::IxNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveIndexStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE INDEX {} ON {}", self.name, self.what)
|
||||
write!(f, "REMOVE INDEX")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " {} ON {}", self.name, self.what)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,13 @@ use serde::{Deserialize, Serialize};
|
|||
use std::fmt::{self, Display};
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
pub struct RemoveModelStatement {
|
||||
pub name: Ident,
|
||||
pub version: String,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveModelStatement {
|
||||
|
@ -24,25 +26,39 @@ impl RemoveModelStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Model, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::database::ml::new(opt.ns(), opt.db(), &self.name, &self.version);
|
||||
run.del(key).await?;
|
||||
// Remove the model file
|
||||
// TODO
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Model, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::database::ml::new(opt.ns(), opt.db(), &self.name, &self.version);
|
||||
run.del(key).await?;
|
||||
// Remove the model file
|
||||
// TODO
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::MlNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveModelStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// Bypass ident display since we don't want backticks arround the ident.
|
||||
write!(f, "REMOVE MODEL ml::{}<{}>", self.name.0, self.version)
|
||||
write!(f, "REMOVE MODEL")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " ml::{}<{}>", self.name.0, self.version)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ use std::fmt::{self, Display, Formatter};
|
|||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
pub struct RemoveNamespaceStatement {
|
||||
pub name: Ident,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveNamespaceStatement {
|
||||
|
@ -23,26 +25,42 @@ impl RemoveNamespaceStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Namespace, &Base::Root)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
ctx.get_index_stores().namespace_removed(opt, &mut run).await?;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::root::ns::new(&self.name);
|
||||
run.del(key).await?;
|
||||
// Delete the resource data
|
||||
let key = crate::key::namespace::all::new(&self.name);
|
||||
run.delp(key, u32::MAX).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Namespace, &Base::Root)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
ctx.get_index_stores().namespace_removed(opt, &mut run).await?;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let ns = run.get_ns(&self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::root::ns::new(&ns.name);
|
||||
run.del(key).await?;
|
||||
// Delete the resource data
|
||||
let key = crate::key::namespace::all::new(&ns.name);
|
||||
run.delp(key, u32::MAX).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::NsNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveNamespaceStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE NAMESPACE {}", self.name)
|
||||
write!(f, "REMOVE NAMESPACE")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " {}", self.name)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,12 @@ use serde::{Deserialize, Serialize};
|
|||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
pub struct RemoveParamStatement {
|
||||
pub name: Ident,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveParamStatement {
|
||||
|
@ -23,22 +25,38 @@ impl RemoveParamStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Parameter, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::database::pa::new(opt.ns(), opt.db(), &self.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Parameter, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let pa = run.get_db_param(opt.ns(), opt.db(), &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::database::pa::new(opt.ns(), opt.db(), &pa.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::PaNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveParamStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE PARAM {}", self.name)
|
||||
write!(f, "REMOVE PARAM")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " ${}", self.name)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ use std::fmt::{self, Display, Formatter};
|
|||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
pub struct RemoveScopeStatement {
|
||||
pub name: Ident,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveScopeStatement {
|
||||
|
@ -23,25 +25,41 @@ impl RemoveScopeStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Scope, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::database::sc::new(opt.ns(), opt.db(), &self.name);
|
||||
run.del(key).await?;
|
||||
// Remove the resource data
|
||||
let key = crate::key::scope::all::new(opt.ns(), opt.db(), &self.name);
|
||||
run.delp(key, u32::MAX).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Scope, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let sc = run.get_sc(opt.ns(), opt.db(), &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::database::sc::new(opt.ns(), opt.db(), &sc.name);
|
||||
run.del(key).await?;
|
||||
// Remove the resource data
|
||||
let key = crate::key::scope::all::new(opt.ns(), opt.db(), &sc.name);
|
||||
run.delp(key, u32::MAX).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::ScNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveScopeStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE SCOPE {}", self.name)
|
||||
write!(f, "REMOVE SCOPE")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " {}", self.name)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,52 +26,52 @@ impl RemoveTableStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Table, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Remove the index stores
|
||||
ctx.get_index_stores().table_removed(opt, &mut run, &self.name).await?;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the defined table
|
||||
match run.get_tb(opt.ns(), opt.db(), &self.name).await {
|
||||
Ok(tb) => {
|
||||
// Delete the definition
|
||||
let key = crate::key::database::tb::new(opt.ns(), opt.db(), &self.name);
|
||||
run.del(key).await?;
|
||||
// Remove the resource data
|
||||
let key = crate::key::table::all::new(opt.ns(), opt.db(), &self.name);
|
||||
run.delp(key, u32::MAX).await?;
|
||||
// Check if this is a foreign table
|
||||
if let Some(view) = &tb.view {
|
||||
// Process each foreign table
|
||||
for v in view.what.0.iter() {
|
||||
// Save the view config
|
||||
let key = crate::key::table::ft::new(opt.ns(), opt.db(), v, &self.name);
|
||||
run.del(key).await?;
|
||||
}
|
||||
}
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
Err(err) => {
|
||||
if matches!(err, Error::TbNotFound { .. }) && self.if_exists {
|
||||
Ok(Value::None)
|
||||
} else {
|
||||
Err(err)
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Table, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Remove the index stores
|
||||
ctx.get_index_stores().table_removed(opt, &mut run, &self.name).await?;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the defined table
|
||||
let tb = run.get_tb(opt.ns(), opt.db(), &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::database::tb::new(opt.ns(), opt.db(), &self.name);
|
||||
run.del(key).await?;
|
||||
// Remove the resource data
|
||||
let key = crate::key::table::all::new(opt.ns(), opt.db(), &self.name);
|
||||
run.delp(key, u32::MAX).await?;
|
||||
// Check if this is a foreign table
|
||||
if let Some(view) = &tb.view {
|
||||
// Process each foreign table
|
||||
for v in view.what.0.iter() {
|
||||
// Save the view config
|
||||
let key = crate::key::table::ft::new(opt.ns(), opt.db(), v, &self.name);
|
||||
run.del(key).await?;
|
||||
}
|
||||
}
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(Error::TbNotFound {
|
||||
..
|
||||
}) if self.if_exists => Ok(Value::None),
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveTableStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE TABLE {}", self.name)?;
|
||||
write!(f, "REMOVE TABLE")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " {}", self.name)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,12 @@ use std::fmt::{self, Display, Formatter};
|
|||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
pub struct RemoveTokenStatement {
|
||||
pub name: Ident,
|
||||
pub base: Base,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveTokenStatement {
|
||||
|
@ -24,50 +26,79 @@ impl RemoveTokenStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Actor, &self.base)?;
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Actor, &self.base)?;
|
||||
|
||||
match &self.base {
|
||||
Base::Ns => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::namespace::tk::new(opt.ns(), &self.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match &self.base {
|
||||
Base::Ns => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let tk = run.get_ns_token(opt.ns(), &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::namespace::tk::new(opt.ns(), &tk.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
Base::Db => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let tk = run.get_db_token(opt.ns(), opt.db(), &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::database::tk::new(opt.ns(), opt.db(), &tk.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
Base::Sc(sc) => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let tk = run.get_sc_token(opt.ns(), opt.db(), sc, &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::scope::tk::new(opt.ns(), opt.db(), sc, &tk.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
_ => Err(Error::InvalidLevel(self.base.to_string())),
|
||||
}
|
||||
Base::Db => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::database::tk::new(opt.ns(), opt.db(), &self.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
Base::Sc(sc) => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::scope::tk::new(opt.ns(), opt.db(), sc, &self.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
_ => Err(Error::InvalidLevel(self.base.to_string())),
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(e) if self.if_exists => match e {
|
||||
Error::NtNotFound {
|
||||
..
|
||||
} => Ok(Value::None),
|
||||
Error::DtNotFound {
|
||||
..
|
||||
} => Ok(Value::None),
|
||||
Error::StNotFound {
|
||||
..
|
||||
} => Ok(Value::None),
|
||||
e => Err(e),
|
||||
},
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveTokenStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE TOKEN {} ON {}", self.name, self.base)
|
||||
write!(f, "REMOVE TOKEN")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " {} ON {}", self.name, self.base)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,13 @@ use serde::{Deserialize, Serialize};
|
|||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[revisioned(revision = 1)]
|
||||
#[revisioned(revision = 2)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
pub struct RemoveUserStatement {
|
||||
pub name: Ident,
|
||||
pub base: Base,
|
||||
#[revision(start = 2)]
|
||||
pub if_exists: bool,
|
||||
}
|
||||
|
||||
impl RemoveUserStatement {
|
||||
|
@ -24,50 +26,79 @@ impl RemoveUserStatement {
|
|||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
) -> Result<Value, Error> {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Actor, &self.base)?;
|
||||
match async {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::Edit, ResourceKind::Actor, &self.base)?;
|
||||
|
||||
match self.base {
|
||||
Base::Root => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Process the statement
|
||||
let key = crate::key::root::us::new(&self.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
match self.base {
|
||||
Base::Root => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let us = run.get_root_user(&self.name).await?;
|
||||
// Process the statement
|
||||
let key = crate::key::root::us::new(&us.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
Base::Ns => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let us = run.get_ns_user(opt.ns(), &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::namespace::us::new(opt.ns(), &us.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
Base::Db => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Get the definition
|
||||
let us = run.get_db_user(opt.ns(), opt.db(), &self.name).await?;
|
||||
// Delete the definition
|
||||
let key = crate::key::database::us::new(opt.ns(), opt.db(), &us.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
_ => Err(Error::InvalidLevel(self.base.to_string())),
|
||||
}
|
||||
Base::Ns => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::namespace::us::new(opt.ns(), &self.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
Base::Db => {
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Delete the definition
|
||||
let key = crate::key::database::us::new(opt.ns(), opt.db(), &self.name);
|
||||
run.del(key).await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
_ => Err(Error::InvalidLevel(self.base.to_string())),
|
||||
}
|
||||
.await
|
||||
{
|
||||
Err(e) if self.if_exists => match e {
|
||||
Error::UserRootNotFound {
|
||||
..
|
||||
} => Ok(Value::None),
|
||||
Error::UserNsNotFound {
|
||||
..
|
||||
} => Ok(Value::None),
|
||||
Error::UserDbNotFound {
|
||||
..
|
||||
} => Ok(Value::None),
|
||||
e => Err(e),
|
||||
},
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RemoveUserStatement {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "REMOVE USER {} ON {}", self.name, self.base)
|
||||
write!(f, "REMOVE USER")?;
|
||||
if self.if_exists {
|
||||
write!(f, " IF EXISTS")?
|
||||
}
|
||||
write!(f, " {} ON {}", self.name, self.base)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ impl ser::Serializer for Serializer {
|
|||
#[derive(Default)]
|
||||
pub struct SerializeRemoveAnalyzerStatement {
|
||||
name: Ident,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveAnalyzerStatement {
|
||||
|
@ -50,6 +51,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveAnalyzerStatement {
|
|||
"name" => {
|
||||
self.name = Ident(value.serialize(ser::string::Serializer.wrap())?);
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveAnalyzerStatement::{key}`"
|
||||
|
@ -62,6 +66,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveAnalyzerStatement {
|
|||
fn end(self) -> Result<Self::Ok, Error> {
|
||||
Ok(RemoveAnalyzerStatement {
|
||||
name: self.name,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ impl ser::Serializer for Serializer {
|
|||
#[derive(Default)]
|
||||
pub struct SerializeRemoveDatabaseStatement {
|
||||
name: Ident,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveDatabaseStatement {
|
||||
|
@ -50,6 +51,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveDatabaseStatement {
|
|||
"name" => {
|
||||
self.name = Ident(value.serialize(ser::string::Serializer.wrap())?);
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveDatabaseStatement::{key}`"
|
||||
|
@ -62,6 +66,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveDatabaseStatement {
|
|||
fn end(self) -> Result<Self::Ok, Error> {
|
||||
Ok(RemoveDatabaseStatement {
|
||||
name: self.name,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ impl ser::Serializer for Serializer {
|
|||
pub struct SerializeRemoveEventStatement {
|
||||
name: Ident,
|
||||
what: Ident,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveEventStatement {
|
||||
|
@ -54,6 +55,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveEventStatement {
|
|||
"what" => {
|
||||
self.what = Ident(value.serialize(ser::string::Serializer.wrap())?);
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveEventStatement::{key}`"
|
||||
|
@ -67,6 +71,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveEventStatement {
|
|||
Ok(RemoveEventStatement {
|
||||
name: self.name,
|
||||
what: self.what,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ impl ser::Serializer for Serializer {
|
|||
pub struct SerializeRemoveFieldStatement {
|
||||
name: Idiom,
|
||||
what: Ident,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveFieldStatement {
|
||||
|
@ -55,6 +56,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveFieldStatement {
|
|||
"what" => {
|
||||
self.what = Ident(value.serialize(ser::string::Serializer.wrap())?);
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveFieldStatement::{key}`"
|
||||
|
@ -68,6 +72,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveFieldStatement {
|
|||
Ok(RemoveFieldStatement {
|
||||
name: self.name,
|
||||
what: self.what,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ impl ser::Serializer for Serializer {
|
|||
#[derive(Default)]
|
||||
pub struct SerializeRemoveFunctionStatement {
|
||||
name: Ident,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveFunctionStatement {
|
||||
|
@ -50,6 +51,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveFunctionStatement {
|
|||
"name" => {
|
||||
self.name = Ident(value.serialize(ser::string::Serializer.wrap())?);
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?;
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveFunctionStatement::{key}`"
|
||||
|
@ -62,6 +66,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveFunctionStatement {
|
|||
fn end(self) -> Result<Self::Ok, Error> {
|
||||
Ok(RemoveFunctionStatement {
|
||||
name: self.name,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ impl ser::Serializer for Serializer {
|
|||
pub struct SerializeRemoveIndexStatement {
|
||||
name: Ident,
|
||||
what: Ident,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveIndexStatement {
|
||||
|
@ -54,6 +55,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveIndexStatement {
|
|||
"what" => {
|
||||
self.what = Ident(value.serialize(ser::string::Serializer.wrap())?);
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?;
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveIndexStatement::{key}`"
|
||||
|
@ -67,6 +71,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveIndexStatement {
|
|||
Ok(RemoveIndexStatement {
|
||||
name: self.name,
|
||||
what: self.what,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ impl ser::Serializer for Serializer {
|
|||
#[derive(Default)]
|
||||
pub struct SerializeRemoveNamespaceStatement {
|
||||
name: Ident,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveNamespaceStatement {
|
||||
|
@ -50,6 +51,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveNamespaceStatement {
|
|||
"name" => {
|
||||
self.name = Ident(value.serialize(ser::string::Serializer.wrap())?);
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?;
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveNamespaceStatement::{key}`"
|
||||
|
@ -62,6 +66,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveNamespaceStatement {
|
|||
fn end(self) -> Result<Self::Ok, Error> {
|
||||
Ok(RemoveNamespaceStatement {
|
||||
name: self.name,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ impl ser::Serializer for Serializer {
|
|||
#[derive(Default)]
|
||||
pub struct SerializeRemoveParamStatement {
|
||||
name: Ident,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveParamStatement {
|
||||
|
@ -50,6 +51,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveParamStatement {
|
|||
"name" => {
|
||||
self.name = Ident(value.serialize(ser::string::Serializer.wrap())?);
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?;
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveParamStatement::{key}`"
|
||||
|
@ -62,6 +66,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveParamStatement {
|
|||
fn end(self) -> Result<Self::Ok, Error> {
|
||||
Ok(RemoveParamStatement {
|
||||
name: self.name,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ impl ser::Serializer for Serializer {
|
|||
#[derive(Default)]
|
||||
pub struct SerializeRemoveScopeStatement {
|
||||
name: Ident,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveScopeStatement {
|
||||
|
@ -50,6 +51,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveScopeStatement {
|
|||
"name" => {
|
||||
self.name = Ident(value.serialize(ser::string::Serializer.wrap())?);
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?;
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveScopeStatement::{key}`"
|
||||
|
@ -62,6 +66,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveScopeStatement {
|
|||
fn end(self) -> Result<Self::Ok, Error> {
|
||||
Ok(RemoveScopeStatement {
|
||||
name: self.name,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ impl ser::Serializer for Serializer {
|
|||
pub struct SerializeRemoveTokenStatement {
|
||||
name: Ident,
|
||||
base: Base,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveTokenStatement {
|
||||
|
@ -55,6 +56,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveTokenStatement {
|
|||
"base" => {
|
||||
self.base = value.serialize(ser::base::Serializer.wrap())?;
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?;
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveTokenStatement::{key}`"
|
||||
|
@ -68,6 +72,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveTokenStatement {
|
|||
Ok(RemoveTokenStatement {
|
||||
name: self.name,
|
||||
base: self.base,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ impl ser::Serializer for Serializer {
|
|||
pub struct SerializeRemoveUserStatement {
|
||||
name: Ident,
|
||||
base: Base,
|
||||
if_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeRemoveUserStatement {
|
||||
|
@ -55,6 +56,9 @@ impl serde::ser::SerializeStruct for SerializeRemoveUserStatement {
|
|||
"base" => {
|
||||
self.base = value.serialize(ser::base::Serializer.wrap())?;
|
||||
}
|
||||
"if_exists" => {
|
||||
self.if_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?;
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `RemoveUserStatement::{key}`"
|
||||
|
@ -68,6 +72,7 @@ impl serde::ser::SerializeStruct for SerializeRemoveUserStatement {
|
|||
Ok(RemoveUserStatement {
|
||||
name: self.name,
|
||||
base: self.base,
|
||||
if_exists: self.if_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,30 +41,52 @@ pub fn remove(i: &str) -> IResult<&str, RemoveStatement> {
|
|||
|
||||
pub fn analyzer(i: &str) -> IResult<&str, RemoveAnalyzerStatement> {
|
||||
let (i, _) = tag_no_case("ANALYZER")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
Ok((
|
||||
i,
|
||||
RemoveAnalyzerStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn database(i: &str) -> IResult<&str, RemoveDatabaseStatement> {
|
||||
let (i, _) = alt((tag_no_case("DB"), tag_no_case("DATABASE")))(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
Ok((
|
||||
i,
|
||||
RemoveDatabaseStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn event(i: &str) -> IResult<&str, RemoveEventStatement> {
|
||||
let (i, _) = tag_no_case("EVENT")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
|
@ -77,12 +99,20 @@ pub fn event(i: &str) -> IResult<&str, RemoveEventStatement> {
|
|||
RemoveEventStatement {
|
||||
name,
|
||||
what,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn field(i: &str) -> IResult<&str, RemoveFieldStatement> {
|
||||
let (i, _) = tag_no_case("FIELD")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(idiom::local)(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
|
@ -95,12 +125,20 @@ pub fn field(i: &str) -> IResult<&str, RemoveFieldStatement> {
|
|||
RemoveFieldStatement {
|
||||
name,
|
||||
what,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn function(i: &str) -> IResult<&str, RemoveFunctionStatement> {
|
||||
let (i, _) = tag_no_case("FUNCTION")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, _) = tag("fn::")(i)?;
|
||||
let (i, name) = ident_path(i)?;
|
||||
|
@ -115,12 +153,20 @@ pub fn function(i: &str) -> IResult<&str, RemoveFunctionStatement> {
|
|||
i,
|
||||
RemoveFunctionStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn index(i: &str) -> IResult<&str, RemoveIndexStatement> {
|
||||
let (i, _) = tag_no_case("INDEX")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
|
@ -133,24 +179,40 @@ pub fn index(i: &str) -> IResult<&str, RemoveIndexStatement> {
|
|||
RemoveIndexStatement {
|
||||
name,
|
||||
what,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn namespace(i: &str) -> IResult<&str, RemoveNamespaceStatement> {
|
||||
let (i, _) = alt((tag_no_case("NS"), tag_no_case("NAMESPACE")))(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
Ok((
|
||||
i,
|
||||
RemoveNamespaceStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn param(i: &str) -> IResult<&str, RemoveParamStatement> {
|
||||
let (i, _) = tag_no_case("PARAM")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, _) = cut(char('$'))(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
|
@ -158,32 +220,42 @@ pub fn param(i: &str) -> IResult<&str, RemoveParamStatement> {
|
|||
i,
|
||||
RemoveParamStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn scope(i: &str) -> IResult<&str, RemoveScopeStatement> {
|
||||
let (i, _) = tag_no_case("SCOPE")(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
Ok((
|
||||
i,
|
||||
RemoveScopeStatement {
|
||||
name,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn table(i: &str) -> IResult<&str, RemoveTableStatement> {
|
||||
let (i, _) = tag_no_case("TABLE")(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
Ok((
|
||||
i,
|
||||
RemoveScopeStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn table(i: &str) -> IResult<&str, RemoveTableStatement> {
|
||||
let (i, _) = tag_no_case("TABLE")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
Ok((
|
||||
i,
|
||||
RemoveTableStatement {
|
||||
|
@ -196,6 +268,12 @@ pub fn table(i: &str) -> IResult<&str, RemoveTableStatement> {
|
|||
|
||||
pub fn token(i: &str) -> IResult<&str, RemoveTokenStatement> {
|
||||
let (i, _) = tag_no_case("TOKEN")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
|
@ -207,12 +285,20 @@ pub fn token(i: &str) -> IResult<&str, RemoveTokenStatement> {
|
|||
RemoveTokenStatement {
|
||||
name,
|
||||
base,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn user(i: &str) -> IResult<&str, RemoveUserStatement> {
|
||||
let (i, _) = tag_no_case("USER")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
|
@ -224,6 +310,8 @@ pub fn user(i: &str) -> IResult<&str, RemoveUserStatement> {
|
|||
RemoveUserStatement {
|
||||
name,
|
||||
base,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: if_exists.is_some(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
@ -238,9 +326,149 @@ mod tests {
|
|||
fn check_remove_serialize() {
|
||||
let stm = RemoveStatement::Namespace(RemoveNamespaceStatement {
|
||||
name: Ident::from("test"),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
});
|
||||
let enc: Vec<u8> = stm.try_into().unwrap();
|
||||
#[cfg(not(feature = "sql2"))]
|
||||
assert_eq!(9, enc.len());
|
||||
#[cfg(feature = "sql2")]
|
||||
assert_eq!(10, enc.len());
|
||||
}
|
||||
|
||||
/// REMOVE ANALYZER tests
|
||||
|
||||
#[test]
|
||||
fn remove_analyzer() {
|
||||
let sql = "REMOVE ANALYZER test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE ANALYZER test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_analyzer_if_exists() {
|
||||
let sql = "REMOVE ANALYZER IF EXISTS test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE ANALYZER IF EXISTS test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_analyzer_if() {
|
||||
let sql = "REMOVE ANALYZER IF test";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
/// REMOVE DATABASE tests
|
||||
|
||||
#[test]
|
||||
fn remove_database() {
|
||||
let sql = "REMOVE DATABASE test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE DATABASE test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_database_if_exists() {
|
||||
let sql = "REMOVE DATABASE IF EXISTS test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE DATABASE IF EXISTS test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_database_if() {
|
||||
let sql = "REMOVE DATABASE IF test";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
/// REMOVE EVENT tests
|
||||
|
||||
#[test]
|
||||
fn remove_event() {
|
||||
let sql = "REMOVE EVENT test ON test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE EVENT test ON test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_event_if_exists() {
|
||||
let sql = "REMOVE EVENT IF EXISTS test ON test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE EVENT IF EXISTS test ON test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_event_if() {
|
||||
let sql = "REMOVE EVENT IF test ON test";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
/// REMOVE FIELD tests
|
||||
|
||||
#[test]
|
||||
fn remove_field() {
|
||||
let sql = "REMOVE FIELD test ON test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE FIELD test ON test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_field_if_exists() {
|
||||
let sql = "REMOVE FIELD IF EXISTS test ON test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE FIELD IF EXISTS test ON test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_field_if() {
|
||||
let sql = "REMOVE FIELD IF test ON test";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
/// REMOVE FUNCTION tests
|
||||
|
||||
#[test]
|
||||
fn remove_function() {
|
||||
let sql = "REMOVE FUNCTION fn::test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE FUNCTION fn::test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_function_if_exists() {
|
||||
let sql = "REMOVE FUNCTION IF EXISTS fn::test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE FUNCTION IF EXISTS fn::test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_function_if() {
|
||||
let sql = "REMOVE FUNCTION IF fn::test";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -251,6 +479,116 @@ mod tests {
|
|||
assert_eq!("REMOVE FUNCTION fn::foo::bar::baz::bac", format!("{}", out))
|
||||
}
|
||||
|
||||
/// REMOVE INDEX tests
|
||||
|
||||
#[test]
|
||||
fn remove_index() {
|
||||
let sql = "REMOVE INDEX test ON test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE INDEX test ON test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_index_if_exists() {
|
||||
let sql = "REMOVE INDEX IF EXISTS test ON test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE INDEX IF EXISTS test ON test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_index_if() {
|
||||
let sql = "REMOVE INDEX IF test ON test";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
/// REMOVE NAMESPACE tests
|
||||
|
||||
#[test]
|
||||
fn remove_namespace() {
|
||||
let sql = "REMOVE NAMESPACE test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE NAMESPACE test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_namespace_if_exists() {
|
||||
let sql = "REMOVE NAMESPACE IF EXISTS test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE NAMESPACE IF EXISTS test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_namespace_if() {
|
||||
let sql = "REMOVE NAMESPACE IF test";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
/// REMOVE PARAM tests
|
||||
|
||||
#[test]
|
||||
fn remove_param() {
|
||||
let sql = "REMOVE PARAM $test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE PARAM $test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_param_if_exists() {
|
||||
let sql = "REMOVE PARAM IF EXISTS $test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE PARAM IF EXISTS $test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_param_if() {
|
||||
let sql = "REMOVE PARAM IF $test";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
/// REMOVE SCOPE tests
|
||||
|
||||
#[test]
|
||||
fn remove_scope() {
|
||||
let sql = "REMOVE SCOPE test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE SCOPE test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_scope_if_exists() {
|
||||
let sql = "REMOVE SCOPE IF EXISTS test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE SCOPE IF EXISTS test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_scope_if() {
|
||||
let sql = "REMOVE SCOPE IF test";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
/// REMOVE TABLE tests
|
||||
|
||||
#[test]
|
||||
fn remove_table() {
|
||||
let sql = "REMOVE TABLE test";
|
||||
|
@ -262,16 +600,70 @@ mod tests {
|
|||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_table_if_exists() {
|
||||
let sql = "REMOVE TABLE test IF EXISTS";
|
||||
let sql = "REMOVE TABLE IF EXISTS test";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE TABLE test IF EXISTS", format!("{}", out))
|
||||
assert_eq!("REMOVE TABLE IF EXISTS test", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_table_if() {
|
||||
let sql = "REMOVE TABLE test IF";
|
||||
let sql = "REMOVE TABLE IF test";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
/// REMOVE TOKEN tests
|
||||
|
||||
#[test]
|
||||
fn remove_token() {
|
||||
let sql = "REMOVE TOKEN test ON NAMESPACE";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE TOKEN test ON NAMESPACE", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_token_if_exists() {
|
||||
let sql = "REMOVE TOKEN IF EXISTS test ON NAMESPACE";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE TOKEN IF EXISTS test ON NAMESPACE", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_token_if() {
|
||||
let sql = "REMOVE TOKEN IF test ON NAMESPACE";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
/// REMOVE USER tests
|
||||
|
||||
#[test]
|
||||
fn remove_user() {
|
||||
let sql = "REMOVE USER test ON ROOT";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE USER test ON ROOT", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_user_if_exists() {
|
||||
let sql = "REMOVE USER IF EXISTS test ON ROOT";
|
||||
let res = remove(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("REMOVE USER IF EXISTS test ON ROOT", format!("{}", out))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "sql2")]
|
||||
fn remove_user_if() {
|
||||
let sql = "REMOVE USER IF test ON ROOT";
|
||||
let res = remove(sql);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
|
|
@ -21,50 +21,6 @@ impl Parser<'_> {
|
|||
pub fn parse_remove_stmt(&mut self) -> ParseResult<RemoveStatement> {
|
||||
let res = match self.next().kind {
|
||||
t!("NAMESPACE") => {
|
||||
let name = self.next_token_value()?;
|
||||
RemoveStatement::Namespace(RemoveNamespaceStatement {
|
||||
name,
|
||||
})
|
||||
}
|
||||
t!("DATABASE") => {
|
||||
let name = self.next_token_value()?;
|
||||
RemoveStatement::Database(RemoveDatabaseStatement {
|
||||
name,
|
||||
})
|
||||
}
|
||||
t!("FUNCTION") => {
|
||||
let name = self.parse_custom_function_name()?;
|
||||
let next = self.peek();
|
||||
if self.eat(t!("(")) {
|
||||
self.expect_closing_delimiter(t!(")"), next.span)?;
|
||||
}
|
||||
RemoveStatement::Function(RemoveFunctionStatement {
|
||||
name,
|
||||
})
|
||||
}
|
||||
t!("TOKEN") => {
|
||||
let name = self.next_token_value()?;
|
||||
expected!(self, t!("ON"));
|
||||
let base = self.parse_base(true)?;
|
||||
RemoveStatement::Token(crate::sql::statements::RemoveTokenStatement {
|
||||
name,
|
||||
base,
|
||||
})
|
||||
}
|
||||
t!("SCOPE") => {
|
||||
let name = self.next_token_value()?;
|
||||
RemoveStatement::Scope(RemoveScopeStatement {
|
||||
name,
|
||||
})
|
||||
}
|
||||
t!("PARAM") => {
|
||||
let name = self.next_token_value::<Param>()?;
|
||||
RemoveStatement::Param(RemoveParamStatement {
|
||||
name: name.0,
|
||||
})
|
||||
}
|
||||
t!("TABLE") => {
|
||||
let name = self.next_token_value()?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
|
@ -72,6 +28,110 @@ impl Parser<'_> {
|
|||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
|
||||
RemoveStatement::Namespace(RemoveNamespaceStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
t!("DATABASE") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
|
||||
RemoveStatement::Database(RemoveDatabaseStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
t!("FUNCTION") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.parse_custom_function_name()?;
|
||||
let next = self.peek();
|
||||
if self.eat(t!("(")) {
|
||||
self.expect_closing_delimiter(t!(")"), next.span)?;
|
||||
}
|
||||
|
||||
RemoveStatement::Function(RemoveFunctionStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
t!("TOKEN") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
expected!(self, t!("ON"));
|
||||
let base = self.parse_base(true)?;
|
||||
|
||||
RemoveStatement::Token(crate::sql::statements::RemoveTokenStatement {
|
||||
name,
|
||||
base,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
t!("SCOPE") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
|
||||
RemoveStatement::Scope(RemoveScopeStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
t!("PARAM") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value::<Param>()?;
|
||||
|
||||
RemoveStatement::Param(RemoveParamStatement {
|
||||
name: name.0,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
t!("TABLE") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
|
||||
RemoveStatement::Table(crate::sql::statements::RemoveTableStatement {
|
||||
name,
|
||||
|
@ -80,48 +140,98 @@ impl Parser<'_> {
|
|||
})
|
||||
}
|
||||
t!("EVENT") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
expected!(self, t!("ON"));
|
||||
self.eat(t!("TABLE"));
|
||||
let table = self.next_token_value()?;
|
||||
|
||||
RemoveStatement::Event(RemoveEventStatement {
|
||||
name,
|
||||
what: table,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
t!("FIELD") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let idiom = self.parse_local_idiom()?;
|
||||
expected!(self, t!("ON"));
|
||||
self.eat(t!("TABLE"));
|
||||
let table = self.next_token_value()?;
|
||||
|
||||
RemoveStatement::Field(RemoveFieldStatement {
|
||||
name: idiom,
|
||||
what: table,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
t!("INDEX") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
expected!(self, t!("ON"));
|
||||
self.eat(t!("TABLE"));
|
||||
let what = self.next_token_value()?;
|
||||
|
||||
RemoveStatement::Index(RemoveIndexStatement {
|
||||
name,
|
||||
what,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
t!("ANALYZER") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
|
||||
RemoveStatement::Analyzer(RemoveAnalyzerStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
t!("USER") => {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
expected!(self, t!("ON"));
|
||||
let base = self.parse_base(false)?;
|
||||
|
||||
RemoveStatement::User(RemoveUserStatement {
|
||||
name,
|
||||
base,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists,
|
||||
})
|
||||
}
|
||||
x => unexpected!(self, x, "a remove statement keyword"),
|
||||
|
|
|
@ -1057,7 +1057,9 @@ fn parse_remove() {
|
|||
assert_eq!(
|
||||
res,
|
||||
Statement::Remove(RemoveStatement::Namespace(RemoveNamespaceStatement {
|
||||
name: Ident("ns".to_owned())
|
||||
name: Ident("ns".to_owned()),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -1065,7 +1067,9 @@ fn parse_remove() {
|
|||
assert_eq!(
|
||||
res,
|
||||
Statement::Remove(RemoveStatement::Database(RemoveDatabaseStatement {
|
||||
name: Ident("database".to_owned())
|
||||
name: Ident("database".to_owned()),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -1073,14 +1077,18 @@ fn parse_remove() {
|
|||
assert_eq!(
|
||||
res,
|
||||
Statement::Remove(RemoveStatement::Function(RemoveFunctionStatement {
|
||||
name: Ident("foo::bar".to_owned())
|
||||
name: Ident("foo::bar".to_owned()),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
let res = test_parse!(parse_stmt, r#"REMOVE FUNCTION fn::foo::bar();"#).unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
Statement::Remove(RemoveStatement::Function(RemoveFunctionStatement {
|
||||
name: Ident("foo::bar".to_owned())
|
||||
name: Ident("foo::bar".to_owned()),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -1089,7 +1097,9 @@ fn parse_remove() {
|
|||
res,
|
||||
Statement::Remove(RemoveStatement::Token(RemoveTokenStatement {
|
||||
name: Ident("foo".to_owned()),
|
||||
base: Base::Sc(Ident("bar".to_owned()))
|
||||
base: Base::Sc(Ident("bar".to_owned())),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -1098,6 +1108,8 @@ fn parse_remove() {
|
|||
res,
|
||||
Statement::Remove(RemoveStatement::Scope(RemoveScopeStatement {
|
||||
name: Ident("foo".to_owned()),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -1106,6 +1118,8 @@ fn parse_remove() {
|
|||
res,
|
||||
Statement::Remove(RemoveStatement::Param(RemoveParamStatement {
|
||||
name: Ident("foo".to_owned()),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -1125,6 +1139,8 @@ fn parse_remove() {
|
|||
Statement::Remove(RemoveStatement::Event(RemoveEventStatement {
|
||||
name: Ident("foo".to_owned()),
|
||||
what: Ident("bar".to_owned()),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -1138,6 +1154,8 @@ fn parse_remove() {
|
|||
Part::Index(Number::Int(10))
|
||||
]),
|
||||
what: Ident("bar".to_owned()),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -1147,6 +1165,8 @@ fn parse_remove() {
|
|||
Statement::Remove(RemoveStatement::Index(RemoveIndexStatement {
|
||||
name: Ident("foo".to_owned()),
|
||||
what: Ident("bar".to_owned()),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -1155,6 +1175,8 @@ fn parse_remove() {
|
|||
res,
|
||||
Statement::Remove(RemoveStatement::Analyzer(RemoveAnalyzerStatement {
|
||||
name: Ident("foo".to_owned()),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -1164,6 +1186,8 @@ fn parse_remove() {
|
|||
Statement::Remove(RemoveStatement::User(RemoveUserStatement {
|
||||
name: Ident("foo".to_owned()),
|
||||
base: Base::Db,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_exists: false,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -589,6 +589,7 @@ fn statements() -> Vec<Statement> {
|
|||
}),
|
||||
Statement::Remove(RemoveStatement::Function(RemoveFunctionStatement {
|
||||
name: Ident("foo::bar".to_owned()),
|
||||
if_exists: false,
|
||||
})),
|
||||
Statement::Remove(RemoveStatement::Field(RemoveFieldStatement {
|
||||
name: Idiom(vec![
|
||||
|
@ -597,6 +598,7 @@ fn statements() -> Vec<Statement> {
|
|||
Part::Index(Number::Int(10)),
|
||||
]),
|
||||
what: Ident("bar".to_owned()),
|
||||
if_exists: false,
|
||||
})),
|
||||
Statement::Update(UpdateStatement {
|
||||
only: true,
|
||||
|
|
|
@ -149,9 +149,383 @@ async fn should_error_when_remove_and_table_does_not_exist() -> Result<(), Error
|
|||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_if_exists() -> Result<(), Error> {
|
||||
async fn should_not_error_when_remove_table_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE TABLE foo IF EXISTS;
|
||||
REMOVE TABLE IF EXISTS foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_analyzer_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE ANALYZER foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::AzNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_analyzer_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE ANALYZER IF EXISTS foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_database_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE DATABASE foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::DbNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_database_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE DATABASE IF EXISTS foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_event_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE EVENT foo ON bar;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::EvNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_event_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE EVENT IF EXISTS foo ON bar;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_field_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE FIELD foo ON bar;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::FdNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_field_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE FIELD IF EXISTS foo ON bar;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_function_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE FUNCTION fn::foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::FcNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_function_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE FUNCTION IF EXISTS fn::foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_index_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE INDEX foo ON bar;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::IxNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_index_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE INDEX IF EXISTS foo ON bar;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_namespace_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE NAMESPACE foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::NsNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_namespace_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE NAMESPACE IF EXISTS foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_param_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE PARAM $foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::PaNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_param_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE PARAM IF EXISTS $foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_scope_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE SCOPE foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::ScNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_scope_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE SCOPE IF EXISTS foo;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_token_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE TOKEN foo ON NAMESPACE;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::NtNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_token_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE TOKEN IF EXISTS foo ON NAMESPACE;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_error_when_remove_and_user_does_not_exist() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE USER foo ON ROOT;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::UserRootNotFound { .. }),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn should_not_error_when_remove_user_if_exists() -> Result<(), Error> {
|
||||
let sql = "
|
||||
REMOVE USER IF EXISTS foo ON ROOT;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
|
|
Loading…
Reference in a new issue