Implement IF NOT EXISTS
-clause on DEFINE
-statements (#3584)
This commit is contained in:
parent
c704cde843
commit
e637a538d2
46 changed files with 1400 additions and 94 deletions
|
@ -794,6 +794,128 @@ pub enum Error {
|
|||
#[error("The db is running without an available storage engine")]
|
||||
MissingStorageEngine,
|
||||
|
||||
/// The requested analyzer already exists
|
||||
#[error("The analyzer '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
AzAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested database already exists
|
||||
#[error("The database '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
DbAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested event already exists
|
||||
#[error("The event '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
EvAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested field already exists
|
||||
#[error("The field '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
FdAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested function already exists
|
||||
#[error("The function 'fn::{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
FcAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested index already exists
|
||||
#[error("The index '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
IxAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested model already exists
|
||||
#[error("The model '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
MlAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested namespace already exists
|
||||
#[error("The namespace '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
NsAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested param already exists
|
||||
#[error("The param '${value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
PaAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested scope already exists
|
||||
#[error("The scope '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
ScAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested table already exists
|
||||
#[error("The table '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
TbAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested namespace token already exists
|
||||
#[error("The namespace token '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
NtAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested database token already exists
|
||||
#[error("The database token '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
DtAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested scope token already exists
|
||||
#[error("The scope token '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
StAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested user already exists
|
||||
#[error("The user '{value}' already exists")]
|
||||
#[cfg(feature = "sql2")]
|
||||
UserRootAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
||||
/// The requested namespace user already exists
|
||||
#[error("The user '{value}' already exists in the namespace '{ns}'")]
|
||||
#[cfg(feature = "sql2")]
|
||||
UserNsAlreadyExists {
|
||||
value: String,
|
||||
ns: String,
|
||||
},
|
||||
|
||||
/// The requested database user already exists
|
||||
#[error("The user '{value}' already exists in the database '{db}'")]
|
||||
#[cfg(feature = "sql2")]
|
||||
UserDbAlreadyExists {
|
||||
value: String,
|
||||
ns: String,
|
||||
db: String,
|
||||
},
|
||||
|
||||
/// The session has expired either because the token used
|
||||
/// to establish it has expired or because an expiration
|
||||
/// was explicitly defined when establishing it
|
||||
|
|
|
@ -25,7 +25,7 @@ async fn table_definitions_can_be_scanned() {
|
|||
view: None,
|
||||
permissions: Default::default(),
|
||||
changefeed: None,
|
||||
comment: None,
|
||||
..Default::default()
|
||||
};
|
||||
tx.set(&key, &value).await.unwrap();
|
||||
|
||||
|
@ -70,6 +70,8 @@ async fn table_definitions_can_be_deleted() {
|
|||
permissions: Default::default(),
|
||||
changefeed: None,
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
};
|
||||
tx.set(&key, &value).await.unwrap();
|
||||
|
||||
|
|
|
@ -2057,7 +2057,7 @@ impl Transaction {
|
|||
db: &str,
|
||||
tb: &str,
|
||||
ix: &str,
|
||||
) -> Result<DefineFieldStatement, Error> {
|
||||
) -> Result<DefineIndexStatement, 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));
|
||||
|
|
|
@ -37,7 +37,7 @@ impl DefineDatabaseStatement {
|
|||
// Process the statement
|
||||
let key = crate::key::namespace::db::new(opt.ns(), &self.name);
|
||||
let ns = run.add_ns(opt.ns(), opt.strict).await?;
|
||||
// Set the id
|
||||
// Store the db
|
||||
if self.id.is_none() && ns.id.is_some() {
|
||||
let mut db = self.clone();
|
||||
db.id = Some(run.get_next_db_id(ns.id.unwrap()).await?);
|
||||
|
|
|
@ -11,7 +11,7 @@ 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 = 2)]
|
||||
#[revisioned(revision = 3)]
|
||||
pub struct DefineAnalyzerStatement {
|
||||
pub name: Ident,
|
||||
#[revision(start = 2)]
|
||||
|
@ -19,6 +19,8 @@ pub struct DefineAnalyzerStatement {
|
|||
pub tokenizers: Option<Vec<Tokenizer>>,
|
||||
pub filters: Option<Vec<Filter>>,
|
||||
pub comment: Option<Strand>,
|
||||
#[revision(start = 3)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineAnalyzerStatement {
|
||||
|
@ -35,11 +37,26 @@ impl DefineAnalyzerStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if analyzer already exists
|
||||
if self.if_not_exists && run.get_db_analyzer(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
return Err(Error::AzAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::az::new(opt.ns(), opt.db(), &self.name);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
// Persist the definition
|
||||
run.set(
|
||||
key,
|
||||
DefineAnalyzerStatement {
|
||||
// Don't persist the "IF NOT EXISTS" clause to schema
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Release the transaction
|
||||
drop(run); // Do we really need this?
|
||||
// Ok all good
|
||||
|
@ -49,7 +66,11 @@ impl DefineAnalyzerStatement {
|
|||
|
||||
impl Display for DefineAnalyzerStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE ANALYZER {}", self.name)?;
|
||||
write!(f, "DEFINE ANALYZER")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " {}", self.name)?;
|
||||
if let Some(ref i) = self.function {
|
||||
write!(f, " FUNCTION fn::{i}")?
|
||||
}
|
||||
|
|
|
@ -11,12 +11,14 @@ 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 DefineDatabaseStatement {
|
||||
pub id: Option<u32>,
|
||||
pub name: Ident,
|
||||
pub comment: Option<Strand>,
|
||||
pub changefeed: Option<ChangeFeed>,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineDatabaseStatement {
|
||||
|
@ -34,18 +36,34 @@ impl DefineDatabaseStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if database already exists
|
||||
if self.if_not_exists && run.get_db(opt.ns(), &self.name).await.is_ok() {
|
||||
return Err(Error::DbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::namespace::db::new(opt.ns(), &self.name);
|
||||
let ns = run.add_ns(opt.ns(), opt.strict).await?;
|
||||
// Set the id
|
||||
if self.id.is_none() && ns.id.is_some() {
|
||||
let mut db = self.clone();
|
||||
db.id = Some(run.get_next_db_id(ns.id.unwrap()).await?);
|
||||
// Store the db
|
||||
// Set the id
|
||||
let db = DefineDatabaseStatement {
|
||||
id: Some(run.get_next_db_id(ns.id.unwrap()).await?),
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
};
|
||||
|
||||
run.set(key, db).await?;
|
||||
} else {
|
||||
// Store the db
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineDatabaseStatement {
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
|
@ -54,7 +72,11 @@ impl DefineDatabaseStatement {
|
|||
|
||||
impl Display for DefineDatabaseStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE DATABASE {}", self.name)?;
|
||||
write!(f, "DEFINE DATABASE")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " {}", self.name)?;
|
||||
if let Some(ref v) = self.comment {
|
||||
write!(f, " COMMENT {v}")?
|
||||
}
|
||||
|
|
|
@ -11,13 +11,15 @@ 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 DefineEventStatement {
|
||||
pub name: Ident,
|
||||
pub what: Ident,
|
||||
pub when: Value,
|
||||
pub then: Values,
|
||||
pub comment: Option<Strand>,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineEventStatement {
|
||||
|
@ -35,12 +37,27 @@ impl DefineEventStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if event already exists
|
||||
if self.if_not_exists
|
||||
&& run.get_tb_event(opt.ns(), opt.db(), &self.what, &self.name).await.is_ok()
|
||||
{
|
||||
return Err(Error::EvAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::table::ev::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||
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(), &self.what, opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineEventStatement {
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Clear the cache
|
||||
let key = crate::key::table::ev::prefix(opt.ns(), opt.db(), &self.what);
|
||||
run.clr(key).await?;
|
||||
|
@ -51,11 +68,11 @@ impl DefineEventStatement {
|
|||
|
||||
impl Display for DefineEventStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"DEFINE EVENT {} ON {} WHEN {} THEN {}",
|
||||
self.name, self.what, self.when, self.then
|
||||
)?;
|
||||
write!(f, "DEFINE EVENT",)?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " {} ON {} WHEN {} THEN {}", self.name, self.what, self.when, self.then)?;
|
||||
if let Some(ref v) = self.comment {
|
||||
write!(f, " COMMENT {v}")?
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use std::fmt::{self, Display, Write};
|
|||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
#[revisioned(revision = 2)]
|
||||
#[revisioned(revision = 3)]
|
||||
pub struct DefineFieldStatement {
|
||||
pub name: Idiom,
|
||||
pub what: Ident,
|
||||
|
@ -27,6 +27,8 @@ pub struct DefineFieldStatement {
|
|||
pub default: Option<Value>,
|
||||
pub permissions: Permissions,
|
||||
pub comment: Option<Strand>,
|
||||
#[revision(start = 3)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineFieldStatement {
|
||||
|
@ -44,8 +46,15 @@ impl DefineFieldStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Process the statement
|
||||
// Check if field already exists
|
||||
let fd = self.name.to_string();
|
||||
if self.if_not_exists && run.get_tb_field(opt.ns(), opt.db(), &self.what, &fd).await.is_ok()
|
||||
{
|
||||
return Err(Error::FdAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::table::fd::new(opt.ns(), opt.db(), &self.what, &fd);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||
|
@ -71,6 +80,7 @@ impl DefineFieldStatement {
|
|||
{
|
||||
DefineFieldStatement {
|
||||
kind: Some(cur_kind),
|
||||
if_not_exists: false,
|
||||
..existing.clone()
|
||||
}
|
||||
} else {
|
||||
|
@ -93,7 +103,14 @@ impl DefineFieldStatement {
|
|||
}
|
||||
}
|
||||
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineFieldStatement {
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Clear the cache
|
||||
let key = crate::key::table::fd::prefix(opt.ns(), opt.db(), &self.what);
|
||||
run.clr(key).await?;
|
||||
|
@ -104,7 +121,11 @@ impl DefineFieldStatement {
|
|||
|
||||
impl Display for DefineFieldStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE FIELD {} ON {}", self.name, self.what)?;
|
||||
write!(f, "DEFINE FIELD")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " {} ON {}", self.name, self.what)?;
|
||||
if self.flex {
|
||||
write!(f, " FLEXIBLE")?
|
||||
}
|
||||
|
|
|
@ -14,13 +14,15 @@ use std::fmt::{self, Display, Write};
|
|||
|
||||
#[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 DefineFunctionStatement {
|
||||
pub name: Ident,
|
||||
pub args: Vec<(Ident, Kind)>,
|
||||
pub block: Block,
|
||||
pub comment: Option<Strand>,
|
||||
pub permissions: Permission,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineFunctionStatement {
|
||||
|
@ -38,11 +40,25 @@ impl DefineFunctionStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if function already exists
|
||||
if self.if_not_exists && run.get_db_function(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
return Err(Error::FcAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::fc::new(opt.ns(), opt.db(), &self.name);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineFunctionStatement {
|
||||
// Don't persist the "IF NOT EXISTS" clause to schema
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
|
@ -50,7 +66,11 @@ impl DefineFunctionStatement {
|
|||
|
||||
impl fmt::Display for DefineFunctionStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE FUNCTION fn::{}(", self.name.0)?;
|
||||
write!(f, "DEFINE FUNCTION")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " fn::{}(", self.name.0)?;
|
||||
for (i, (name, kind)) in self.args.iter().enumerate() {
|
||||
if i > 0 {
|
||||
f.write_str(", ")?;
|
||||
|
|
|
@ -11,13 +11,15 @@ 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 DefineIndexStatement {
|
||||
pub name: Ident,
|
||||
pub what: Ident,
|
||||
pub cols: Idioms,
|
||||
pub index: Index,
|
||||
pub comment: Option<Strand>,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineIndexStatement {
|
||||
|
@ -35,12 +37,28 @@ impl DefineIndexStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if index already exists
|
||||
if self.if_not_exists
|
||||
&& run.get_tb_index(opt.ns(), opt.db(), &self.what, &self.name).await.is_ok()
|
||||
{
|
||||
return Err(Error::IxAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::table::ix::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||
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(), &self.what, opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineIndexStatement {
|
||||
// Don't persist the "IF NOT EXISTS" clause to schema
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.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?;
|
||||
|
@ -70,7 +88,11 @@ impl DefineIndexStatement {
|
|||
|
||||
impl Display for DefineIndexStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE INDEX {} ON {} FIELDS {}", self.name, self.what, self.cols)?;
|
||||
write!(f, "DEFINE INDEX")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " {} ON {} FIELDS {}", self.name, self.what, self.cols)?;
|
||||
if Index::Idx != self.index {
|
||||
write!(f, " {}", self.index)?;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,6 @@ mod tests {
|
|||
..Default::default()
|
||||
});
|
||||
let enc: Vec<u8> = stm.try_into().unwrap();
|
||||
assert_eq!(11, enc.len());
|
||||
assert_eq!(12, enc.len());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,18 +14,24 @@ use std::fmt::{self, Write};
|
|||
|
||||
#[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 DefineModelStatement {
|
||||
pub hash: String,
|
||||
pub name: Ident,
|
||||
pub version: String,
|
||||
pub comment: Option<Strand>,
|
||||
pub permissions: Permission,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl fmt::Display for DefineModelStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "DEFINE MODEL ml::{}<{}>", self.name, self.version)?;
|
||||
write!(f, "DEFINE MODEL")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " ml::{}<{}>", self.name, self.version)?;
|
||||
if let Some(comment) = self.comment.as_ref() {
|
||||
write!(f, " COMMENT {}", comment)?;
|
||||
}
|
||||
|
@ -55,11 +61,27 @@ impl DefineModelStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if model already exists
|
||||
if self.if_not_exists
|
||||
&& run.get_db_model(opt.ns(), opt.db(), &self.name, &self.version).await.is_ok()
|
||||
{
|
||||
return Err(Error::MlAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::ml::new(opt.ns(), opt.db(), &self.name, &self.version);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineModelStatement {
|
||||
// Don't persist the "IF NOT EXISTS" clause to schema
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Store the model file
|
||||
// TODO
|
||||
// Ok all good
|
||||
|
|
|
@ -11,11 +11,13 @@ 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 DefineNamespaceStatement {
|
||||
pub id: Option<u32>,
|
||||
pub name: Ident,
|
||||
pub comment: Option<Strand>,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineNamespaceStatement {
|
||||
|
@ -35,13 +37,29 @@ impl DefineNamespaceStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Set the id
|
||||
// Check if namespace already exists
|
||||
if self.if_not_exists && run.get_ns(&self.name).await.is_ok() {
|
||||
return Err(Error::NsAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
if self.id.is_none() {
|
||||
let mut ns = self.clone();
|
||||
ns.id = Some(run.get_next_ns_id().await?);
|
||||
// Set the id
|
||||
let ns = DefineNamespaceStatement {
|
||||
id: Some(run.get_next_ns_id().await?),
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
};
|
||||
run.set(key, ns).await?;
|
||||
} else {
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineNamespaceStatement {
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
|
@ -50,7 +68,11 @@ impl DefineNamespaceStatement {
|
|||
|
||||
impl Display for DefineNamespaceStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE NAMESPACE {}", self.name)?;
|
||||
write!(f, "DEFINE NAMESPACE")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " {}", self.name)?;
|
||||
if let Some(ref v) = self.comment {
|
||||
write!(f, " COMMENT {v}")?
|
||||
}
|
||||
|
|
|
@ -12,12 +12,14 @@ use std::fmt::{self, Display, Write};
|
|||
|
||||
#[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 DefineParamStatement {
|
||||
pub name: Ident,
|
||||
pub value: Value,
|
||||
pub comment: Option<Strand>,
|
||||
pub permissions: Permission,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineParamStatement {
|
||||
|
@ -35,16 +37,27 @@ impl DefineParamStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Compute the param
|
||||
let val = DefineParamStatement {
|
||||
value: self.value.compute(ctx, opt, txn, doc).await?,
|
||||
..self.clone()
|
||||
};
|
||||
// Check if param already exists
|
||||
if self.if_not_exists && run.get_db_param(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
return Err(Error::PaAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::pa::new(opt.ns(), opt.db(), &self.name);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||
run.set(key, val).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineParamStatement {
|
||||
// Compute the param
|
||||
value: self.value.compute(ctx, opt, txn, doc).await?,
|
||||
// Don't persist the "IF NOT EXISTS" clause to schema
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
|
@ -52,7 +65,11 @@ impl DefineParamStatement {
|
|||
|
||||
impl Display for DefineParamStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE PARAM ${} VALUE {}", self.name, self.value)?;
|
||||
write!(f, "DEFINE PARAM")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " ${} VALUE {}", self.name, self.value)?;
|
||||
if let Some(ref v) = self.comment {
|
||||
write!(f, " COMMENT {v}")?
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ 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 DefineScopeStatement {
|
||||
pub name: Ident,
|
||||
pub code: String,
|
||||
|
@ -21,6 +21,8 @@ pub struct DefineScopeStatement {
|
|||
pub signup: Option<Value>,
|
||||
pub signin: Option<Value>,
|
||||
pub comment: Option<Strand>,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineScopeStatement {
|
||||
|
@ -44,11 +46,25 @@ impl DefineScopeStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if scope already exists
|
||||
if self.if_not_exists && run.get_sc(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
return Err(Error::ScAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::sc::new(opt.ns(), opt.db(), &self.name);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineScopeStatement {
|
||||
// Don't persist the "IF NOT EXISTS" clause to schema
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
|
@ -56,7 +72,11 @@ impl DefineScopeStatement {
|
|||
|
||||
impl Display for DefineScopeStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE SCOPE {}", self.name)?;
|
||||
write!(f, "DEFINE SCOPE")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " {}", self.name)?;
|
||||
if let Some(ref v) = self.session {
|
||||
write!(f, " SESSION {v}")?
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ use crate::sql::{
|
|||
|
||||
#[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 DefineTableStatement {
|
||||
pub id: Option<u32>,
|
||||
pub name: Ident,
|
||||
|
@ -28,6 +28,8 @@ pub struct DefineTableStatement {
|
|||
pub permissions: Permissions,
|
||||
pub changefeed: Option<ChangeFeed>,
|
||||
pub comment: Option<Strand>,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineTableStatement {
|
||||
|
@ -44,19 +46,29 @@ impl DefineTableStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if table already exists
|
||||
if self.if_not_exists && run.get_tb(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
return Err(Error::TbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::tb::new(opt.ns(), opt.db(), &self.name);
|
||||
let ns = run.add_ns(opt.ns(), opt.strict).await?;
|
||||
let db = run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||
let dt = if self.id.is_none() && ns.id.is_some() && db.id.is_some() {
|
||||
let mut tb = self.clone();
|
||||
tb.id = Some(run.get_next_tb_id(ns.id.unwrap(), db.id.unwrap()).await?);
|
||||
run.set(key, &tb).await?;
|
||||
tb
|
||||
DefineTableStatement {
|
||||
id: Some(run.get_next_tb_id(ns.id.unwrap(), db.id.unwrap()).await?),
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
}
|
||||
} else {
|
||||
run.set(key, self).await?;
|
||||
self.to_owned()
|
||||
DefineTableStatement {
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
}
|
||||
};
|
||||
run.set(key, &dt).await?;
|
||||
// Check if table is a view
|
||||
if let Some(view) = &self.view {
|
||||
// Remove the table data
|
||||
|
@ -100,7 +112,11 @@ impl DefineTableStatement {
|
|||
|
||||
impl Display for DefineTableStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE TABLE {}", self.name)?;
|
||||
write!(f, "DEFINE TABLE")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(f, " {}", self.name)?;
|
||||
if self.drop {
|
||||
f.write_str(" DROP")?;
|
||||
}
|
||||
|
|
|
@ -11,13 +11,15 @@ 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 DefineTokenStatement {
|
||||
pub name: Ident,
|
||||
pub base: Base,
|
||||
pub kind: Algorithm,
|
||||
pub code: String,
|
||||
pub comment: Option<Strand>,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl DefineTokenStatement {
|
||||
|
@ -37,10 +39,23 @@ impl DefineTokenStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if token already exists
|
||||
if self.if_not_exists && run.get_ns_token(opt.ns(), &self.name).await.is_ok() {
|
||||
return Err(Error::NtAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::namespace::tk::new(opt.ns(), &self.name);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineTokenStatement {
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
|
@ -49,11 +64,26 @@ impl DefineTokenStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if token already exists
|
||||
if self.if_not_exists
|
||||
&& run.get_db_token(opt.ns(), opt.db(), &self.name).await.is_ok()
|
||||
{
|
||||
return Err(Error::DtAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::tk::new(opt.ns(), opt.db(), &self.name);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineTokenStatement {
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
|
@ -62,12 +92,27 @@ impl DefineTokenStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if token already exists
|
||||
if self.if_not_exists
|
||||
&& run.get_sc_token(opt.ns(), opt.db(), sc, &self.name).await.is_ok()
|
||||
{
|
||||
return Err(Error::StAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::scope::tk::new(opt.ns(), opt.db(), sc, &self.name);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||
run.add_sc(opt.ns(), opt.db(), sc, opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineTokenStatement {
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
|
@ -79,9 +124,13 @@ impl DefineTokenStatement {
|
|||
|
||||
impl Display for DefineTokenStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE TOKEN",)?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(
|
||||
f,
|
||||
"DEFINE TOKEN {} ON {} TYPE {} VALUE {}",
|
||||
" {} ON {} TYPE {} VALUE {}",
|
||||
self.name,
|
||||
self.base,
|
||||
self.kind,
|
||||
|
|
|
@ -16,7 +16,7 @@ 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 DefineUserStatement {
|
||||
pub name: Ident,
|
||||
pub base: Base,
|
||||
|
@ -24,6 +24,8 @@ pub struct DefineUserStatement {
|
|||
pub code: String,
|
||||
pub roles: Vec<Ident>,
|
||||
pub comment: Option<Strand>,
|
||||
#[revision(start = 2)]
|
||||
pub if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl From<(Base, &str, &str)> for DefineUserStatement {
|
||||
|
@ -42,6 +44,7 @@ impl From<(Base, &str, &str)> for DefineUserStatement {
|
|||
.collect::<String>(),
|
||||
roles: vec!["owner".into()],
|
||||
comment: None,
|
||||
if_not_exists: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -89,9 +92,23 @@ impl DefineUserStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if user already exists
|
||||
if self.if_not_exists && run.get_root_user(&self.name).await.is_ok() {
|
||||
return Err(Error::UserRootAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::root::us::new(&self.name);
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineUserStatement {
|
||||
// Don't persist the "IF NOT EXISTS" clause to schema
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
|
@ -100,10 +117,25 @@ impl DefineUserStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if user already exists
|
||||
if self.if_not_exists && run.get_ns_user(opt.ns(), &self.name).await.is_ok() {
|
||||
return Err(Error::UserNsAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
ns: opt.ns().into(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::namespace::us::new(opt.ns(), &self.name);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineUserStatement {
|
||||
// Don't persist the "IF NOT EXISTS" clause to schema
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
|
@ -112,11 +144,29 @@ impl DefineUserStatement {
|
|||
let mut run = txn.lock().await;
|
||||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if user already exists
|
||||
if self.if_not_exists
|
||||
&& run.get_db_user(opt.ns(), opt.db(), &self.name).await.is_ok()
|
||||
{
|
||||
return Err(Error::UserDbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
ns: opt.ns().into(),
|
||||
db: opt.db().into(),
|
||||
});
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::us::new(opt.ns(), opt.db(), &self.name);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||
run.set(key, self).await?;
|
||||
run.set(
|
||||
key,
|
||||
DefineUserStatement {
|
||||
// Don't persist the "IF NOT EXISTS" clause to schema
|
||||
if_not_exists: false,
|
||||
..self.clone()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
// Ok all good
|
||||
Ok(Value::None)
|
||||
}
|
||||
|
@ -128,9 +178,13 @@ impl DefineUserStatement {
|
|||
|
||||
impl Display for DefineUserStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DEFINE USER")?;
|
||||
if self.if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?
|
||||
}
|
||||
write!(
|
||||
f,
|
||||
"DEFINE USER {} ON {} PASSHASH {} ROLES {}",
|
||||
" {} ON {} PASSHASH {} ROLES {}",
|
||||
self.name,
|
||||
self.base,
|
||||
quote_str(&self.hash),
|
||||
|
|
|
@ -43,6 +43,7 @@ pub struct SerializeDefineAnalyzerStatement {
|
|||
tokenizers: Option<Vec<Tokenizer>>,
|
||||
filters: Option<Vec<Filter>>,
|
||||
comment: Option<Strand>,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineAnalyzerStatement {
|
||||
|
@ -69,6 +70,9 @@ impl serde::ser::SerializeStruct for SerializeDefineAnalyzerStatement {
|
|||
"comment" => {
|
||||
self.comment = value.serialize(ser::strand::opt::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineAnalyzerStatement::{key}`"
|
||||
|
@ -85,6 +89,7 @@ impl serde::ser::SerializeStruct for SerializeDefineAnalyzerStatement {
|
|||
tokenizers: self.tokenizers,
|
||||
filters: self.filters,
|
||||
comment: self.comment,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ pub struct SerializeDefineDatabaseStatement {
|
|||
changefeed: Option<ChangeFeed>,
|
||||
id: Option<u32>,
|
||||
comment: Option<Strand>,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineDatabaseStatement {
|
||||
|
@ -64,6 +65,9 @@ impl serde::ser::SerializeStruct for SerializeDefineDatabaseStatement {
|
|||
"comment" => {
|
||||
self.comment = value.serialize(ser::strand::opt::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineDatabaseStatement::{key}`"
|
||||
|
@ -79,6 +83,7 @@ impl serde::ser::SerializeStruct for SerializeDefineDatabaseStatement {
|
|||
changefeed: self.changefeed,
|
||||
id: self.id,
|
||||
comment: self.comment,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ pub struct SerializeDefineEventStatement {
|
|||
when: Value,
|
||||
then: Values,
|
||||
comment: Option<Strand>,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineEventStatement {
|
||||
|
@ -69,6 +70,9 @@ impl serde::ser::SerializeStruct for SerializeDefineEventStatement {
|
|||
"comment" => {
|
||||
self.comment = value.serialize(ser::strand::opt::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineEventStatement::{key}`"
|
||||
|
@ -85,6 +89,7 @@ impl serde::ser::SerializeStruct for SerializeDefineEventStatement {
|
|||
when: self.when,
|
||||
then: self.then,
|
||||
comment: self.comment,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ pub struct SerializeDefineFieldStatement {
|
|||
default: Option<Value>,
|
||||
permissions: Permissions,
|
||||
comment: Option<Strand>,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineFieldStatement {
|
||||
|
@ -91,6 +92,9 @@ impl serde::ser::SerializeStruct for SerializeDefineFieldStatement {
|
|||
"comment" => {
|
||||
self.comment = value.serialize(ser::strand::opt::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineFieldStatement::{key}`"
|
||||
|
@ -112,6 +116,7 @@ impl serde::ser::SerializeStruct for SerializeDefineFieldStatement {
|
|||
default: self.default,
|
||||
permissions: self.permissions,
|
||||
comment: self.comment,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ pub struct SerializeDefineFunctionStatement {
|
|||
block: Block,
|
||||
comment: Option<Strand>,
|
||||
permissions: Permission,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineFunctionStatement {
|
||||
|
@ -70,6 +71,9 @@ impl serde::ser::SerializeStruct for SerializeDefineFunctionStatement {
|
|||
"permissions" => {
|
||||
self.permissions = value.serialize(ser::permission::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineFunctionStatement::{key}`"
|
||||
|
@ -86,6 +90,7 @@ impl serde::ser::SerializeStruct for SerializeDefineFunctionStatement {
|
|||
block: self.block,
|
||||
comment: self.comment,
|
||||
permissions: self.permissions,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ pub struct SerializeDefineIndexStatement {
|
|||
cols: Idioms,
|
||||
index: Index,
|
||||
comment: Option<Strand>,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineIndexStatement {
|
||||
|
@ -69,6 +70,9 @@ impl serde::ser::SerializeStruct for SerializeDefineIndexStatement {
|
|||
"comment" => {
|
||||
self.comment = value.serialize(ser::strand::opt::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineIndexStatement::{key}`"
|
||||
|
@ -85,6 +89,7 @@ impl serde::ser::SerializeStruct for SerializeDefineIndexStatement {
|
|||
cols: self.cols,
|
||||
index: self.index,
|
||||
comment: self.comment,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ pub struct SerializeDefineNamespaceStatement {
|
|||
name: Ident,
|
||||
id: Option<u32>,
|
||||
comment: Option<Strand>,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineNamespaceStatement {
|
||||
|
@ -59,6 +60,9 @@ impl serde::ser::SerializeStruct for SerializeDefineNamespaceStatement {
|
|||
"comment" => {
|
||||
self.comment = value.serialize(ser::strand::opt::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineNamespaceStatement::{key}`"
|
||||
|
@ -73,6 +77,7 @@ impl serde::ser::SerializeStruct for SerializeDefineNamespaceStatement {
|
|||
name: self.name,
|
||||
id: self.id,
|
||||
comment: self.comment,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ pub struct SerializeDefineParamStatement {
|
|||
value: Value,
|
||||
comment: Option<Strand>,
|
||||
permissions: Permission,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineParamStatement {
|
||||
|
@ -65,6 +66,9 @@ impl serde::ser::SerializeStruct for SerializeDefineParamStatement {
|
|||
"permissions" => {
|
||||
self.permissions = value.serialize(ser::permission::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineParamStatement::{key}`"
|
||||
|
@ -80,6 +84,7 @@ impl serde::ser::SerializeStruct for SerializeDefineParamStatement {
|
|||
value: self.value,
|
||||
comment: self.comment,
|
||||
permissions: self.permissions,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ pub struct SerializeDefineScopeStatement {
|
|||
signup: Option<Value>,
|
||||
signin: Option<Value>,
|
||||
comment: Option<Strand>,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineScopeStatement {
|
||||
|
@ -74,6 +75,9 @@ impl serde::ser::SerializeStruct for SerializeDefineScopeStatement {
|
|||
"comment" => {
|
||||
self.comment = value.serialize(ser::strand::opt::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineScopeStatement::{key}`"
|
||||
|
@ -91,6 +95,7 @@ impl serde::ser::SerializeStruct for SerializeDefineScopeStatement {
|
|||
signup: self.signup,
|
||||
signin: self.signin,
|
||||
comment: self.comment,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ pub struct SerializeDefineTableStatement {
|
|||
permissions: Permissions,
|
||||
changefeed: Option<ChangeFeed>,
|
||||
comment: Option<Strand>,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineTableStatement {
|
||||
|
@ -82,6 +83,9 @@ impl serde::ser::SerializeStruct for SerializeDefineTableStatement {
|
|||
"comment" => {
|
||||
self.comment = value.serialize(ser::strand::opt::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineTableStatement::{key}`"
|
||||
|
@ -101,6 +105,7 @@ impl serde::ser::SerializeStruct for SerializeDefineTableStatement {
|
|||
permissions: self.permissions,
|
||||
changefeed: self.changefeed,
|
||||
comment: self.comment,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ pub struct SerializeDefineTokenStatement {
|
|||
kind: Algorithm,
|
||||
code: String,
|
||||
comment: Option<Strand>,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineTokenStatement {
|
||||
|
@ -69,6 +70,9 @@ impl serde::ser::SerializeStruct for SerializeDefineTokenStatement {
|
|||
"comment" => {
|
||||
self.comment = value.serialize(ser::strand::opt::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineTokenStatement::{key}`"
|
||||
|
@ -85,6 +89,7 @@ impl serde::ser::SerializeStruct for SerializeDefineTokenStatement {
|
|||
kind: self.kind,
|
||||
code: self.code,
|
||||
comment: self.comment,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ pub struct SerializeDefineUserStatement {
|
|||
code: String,
|
||||
roles: Vec<Ident>,
|
||||
comment: Option<Strand>,
|
||||
if_not_exists: bool,
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStruct for SerializeDefineUserStatement {
|
||||
|
@ -72,6 +73,9 @@ impl serde::ser::SerializeStruct for SerializeDefineUserStatement {
|
|||
"comment" => {
|
||||
self.comment = value.serialize(ser::strand::opt::Serializer.wrap())?;
|
||||
}
|
||||
"if_not_exists" => {
|
||||
self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())?
|
||||
}
|
||||
key => {
|
||||
return Err(Error::custom(format!(
|
||||
"unexpected field `DefineUserStatement::{key}`"
|
||||
|
@ -89,6 +93,7 @@ impl serde::ser::SerializeStruct for SerializeDefineUserStatement {
|
|||
code: self.code,
|
||||
roles: self.roles,
|
||||
comment: self.comment,
|
||||
if_not_exists: self.if_not_exists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,19 @@ use crate::sql::Ident;
|
|||
use crate::sql::{filter::Filter, statements::DefineAnalyzerStatement, Strand, Tokenizer};
|
||||
#[cfg(feature = "sql2")]
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
|
||||
use nom::{
|
||||
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0,
|
||||
sequence::tuple,
|
||||
};
|
||||
|
||||
pub fn analyzer(i: &str) -> IResult<&str, DefineAnalyzerStatement> {
|
||||
let (i, _) = tag_no_case("ANALYZER")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
let (i, opts) = many0(analyzer_opts)(i)?;
|
||||
|
@ -21,6 +30,8 @@ pub fn analyzer(i: &str) -> IResult<&str, DefineAnalyzerStatement> {
|
|||
// Create the base statement
|
||||
let mut res = DefineAnalyzerStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
|
|
@ -7,10 +7,19 @@ use super::super::super::{
|
|||
IResult,
|
||||
};
|
||||
use crate::sql::{statements::DefineDatabaseStatement, ChangeFeed, Strand};
|
||||
use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
|
||||
use nom::{
|
||||
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0,
|
||||
sequence::tuple,
|
||||
};
|
||||
|
||||
pub fn database(i: &str) -> IResult<&str, DefineDatabaseStatement> {
|
||||
let (i, _) = alt((tag_no_case("DB"), tag_no_case("DATABASE")))(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
let (i, opts) = many0(database_opts)(i)?;
|
||||
|
@ -19,6 +28,8 @@ pub fn database(i: &str) -> IResult<&str, DefineDatabaseStatement> {
|
|||
// Create the base statement
|
||||
let mut res = DefineDatabaseStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
@ -58,6 +69,7 @@ fn database_changefeed(i: &str) -> IResult<&str, DefineDatabaseOption> {
|
|||
let (i, v) = changefeed(i)?;
|
||||
Ok((i, DefineDatabaseOption::ChangeFeed(v)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
|
|
|
@ -18,6 +18,12 @@ use nom::{
|
|||
|
||||
pub fn event(i: &str) -> IResult<&str, DefineEventStatement> {
|
||||
let (i, _) = tag_no_case("EVENT")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, (name, what, opts)) = cut(|i| {
|
||||
let (i, name) = ident(i)?;
|
||||
|
@ -35,6 +41,8 @@ pub fn event(i: &str) -> IResult<&str, DefineEventStatement> {
|
|||
name,
|
||||
what,
|
||||
when: Value::Bool(true),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
|
|
@ -20,6 +20,12 @@ use nom::{
|
|||
|
||||
pub fn field(i: &str) -> IResult<&str, DefineFieldStatement> {
|
||||
let (i, _) = tag_no_case("FIELD")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, (name, what, opts)) = cut(|i| {
|
||||
let (i, name) = idiom::local(i)?;
|
||||
|
@ -40,6 +46,8 @@ pub fn field(i: &str) -> IResult<&str, DefineFieldStatement> {
|
|||
let mut res = DefineFieldStatement {
|
||||
name,
|
||||
what,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
|
|
@ -15,11 +15,19 @@ use nom::{
|
|||
bytes::complete::{tag, tag_no_case},
|
||||
character::complete::char,
|
||||
combinator::cut,
|
||||
combinator::opt,
|
||||
multi::many0,
|
||||
sequence::tuple,
|
||||
};
|
||||
|
||||
pub fn function(i: &str) -> IResult<&str, DefineFunctionStatement> {
|
||||
let (i, _) = tag_no_case("FUNCTION")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, _) = tag("fn::")(i)?;
|
||||
let (i, name) = ident_path(i)?;
|
||||
|
@ -47,6 +55,8 @@ pub fn function(i: &str) -> IResult<&str, DefineFunctionStatement> {
|
|||
name,
|
||||
args,
|
||||
block,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
|
|
@ -22,6 +22,12 @@ use nom::{
|
|||
|
||||
pub fn index(i: &str) -> IResult<&str, DefineIndexStatement> {
|
||||
let (i, _) = tag_no_case("INDEX")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, (name, what, opts)) = cut(|i| {
|
||||
let (i, name) = ident(i)?;
|
||||
|
@ -38,6 +44,8 @@ pub fn index(i: &str) -> IResult<&str, DefineIndexStatement> {
|
|||
let mut res = DefineIndexStatement {
|
||||
name,
|
||||
what,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
@ -122,6 +130,8 @@ mod tests {
|
|||
cols: Idioms(vec![Idiom(vec![Part::Field(Ident("my_col".to_string()))])]),
|
||||
index: Index::Idx,
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}
|
||||
);
|
||||
assert_eq!(idx.to_string(), "DEFINE INDEX my_index ON my_table FIELDS my_col");
|
||||
|
@ -139,6 +149,8 @@ mod tests {
|
|||
cols: Idioms(vec![Idiom(vec![Part::Field(Ident("my_col".to_string()))])]),
|
||||
index: Index::Uniq,
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}
|
||||
);
|
||||
assert_eq!(idx.to_string(), "DEFINE INDEX my_index ON my_table FIELDS my_col UNIQUE");
|
||||
|
@ -173,6 +185,8 @@ mod tests {
|
|||
terms_cache: 400,
|
||||
}),
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}
|
||||
);
|
||||
assert_eq!(idx.to_string(), "DEFINE INDEX my_index ON my_table FIELDS my_col SEARCH ANALYZER my_analyzer BM25(1.2,0.75) \
|
||||
|
@ -204,6 +218,8 @@ mod tests {
|
|||
terms_cache: 100,
|
||||
}),
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
|
@ -233,6 +249,8 @@ mod tests {
|
|||
mtree_cache: 100,
|
||||
}),
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
|
@ -6,10 +6,19 @@ use super::super::super::{
|
|||
IResult,
|
||||
};
|
||||
use crate::sql::{statements::DefineNamespaceStatement, Strand};
|
||||
use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
|
||||
use nom::{
|
||||
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0,
|
||||
sequence::tuple,
|
||||
};
|
||||
|
||||
pub fn namespace(i: &str) -> IResult<&str, DefineNamespaceStatement> {
|
||||
let (i, _) = alt((tag_no_case("NS"), tag_no_case("NAMESPACE")))(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
let (i, opts) = many0(namespace_opts)(i)?;
|
||||
|
@ -17,6 +26,8 @@ pub fn namespace(i: &str) -> IResult<&str, DefineNamespaceStatement> {
|
|||
// Create the base statement
|
||||
let mut res = DefineNamespaceStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
@ -36,7 +47,7 @@ enum DefineNamespaceOption {
|
|||
}
|
||||
|
||||
fn namespace_opts(i: &str) -> IResult<&str, DefineNamespaceOption> {
|
||||
namespace_comment(i)
|
||||
alt((namespace_comment,))(i)
|
||||
}
|
||||
|
||||
fn namespace_comment(i: &str) -> IResult<&str, DefineNamespaceOption> {
|
||||
|
|
|
@ -13,11 +13,17 @@ use crate::{
|
|||
};
|
||||
use nom::{
|
||||
branch::alt, bytes::complete::tag_no_case, character::complete::char, combinator::cut,
|
||||
multi::many0, Err,
|
||||
combinator::opt, multi::many0, sequence::tuple, Err,
|
||||
};
|
||||
|
||||
pub fn param(i: &str) -> IResult<&str, DefineParamStatement> {
|
||||
let (i, _) = tag_no_case("PARAM")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, _) = cut(char('$'))(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
|
@ -26,6 +32,8 @@ pub fn param(i: &str) -> IResult<&str, DefineParamStatement> {
|
|||
// Create the base statement
|
||||
let mut res = DefineParamStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
|
|
@ -7,10 +7,19 @@ use super::super::super::{
|
|||
IResult,
|
||||
};
|
||||
use crate::sql::{statements::DefineScopeStatement, Duration, Strand, Value};
|
||||
use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
|
||||
use nom::{
|
||||
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0,
|
||||
sequence::tuple,
|
||||
};
|
||||
|
||||
pub fn scope(i: &str) -> IResult<&str, DefineScopeStatement> {
|
||||
let (i, _) = tag_no_case("SCOPE")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
let (i, opts) = many0(scope_opts)(i)?;
|
||||
|
@ -19,6 +28,8 @@ pub fn scope(i: &str) -> IResult<&str, DefineScopeStatement> {
|
|||
let mut res = DefineScopeStatement {
|
||||
name,
|
||||
code: DefineScopeStatement::random_code(),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
|
|
@ -9,10 +9,19 @@ use super::super::super::{
|
|||
use crate::sql::{
|
||||
statements::DefineTableStatement, ChangeFeed, Permission, Permissions, Strand, View,
|
||||
};
|
||||
use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
|
||||
use nom::{
|
||||
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0,
|
||||
sequence::tuple,
|
||||
};
|
||||
|
||||
pub fn table(i: &str) -> IResult<&str, DefineTableStatement> {
|
||||
let (i, _) = tag_no_case("TABLE")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, name) = cut(ident)(i)?;
|
||||
let (i, opts) = many0(table_opts)(i)?;
|
||||
|
@ -24,6 +33,8 @@ pub fn table(i: &str) -> IResult<&str, DefineTableStatement> {
|
|||
let mut res = DefineTableStatement {
|
||||
name,
|
||||
permissions: Permissions::none(),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
|
|
@ -13,10 +13,19 @@ use crate::{
|
|||
syn::v1::ParseError,
|
||||
};
|
||||
use nom::Err;
|
||||
use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
|
||||
use nom::{
|
||||
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0,
|
||||
sequence::tuple,
|
||||
};
|
||||
|
||||
pub fn token(i: &str) -> IResult<&str, DefineTokenStatement> {
|
||||
let (i, _) = tag_no_case("TOKEN")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, (name, base, opts)) = cut(|i| {
|
||||
let (i, name) = ident(i)?;
|
||||
|
@ -32,6 +41,8 @@ pub fn token(i: &str) -> IResult<&str, DefineTokenStatement> {
|
|||
let mut res = DefineTokenStatement {
|
||||
name,
|
||||
base,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: if_not_exists.is_some(),
|
||||
..Default::default()
|
||||
};
|
||||
// Assign any defined options
|
||||
|
|
|
@ -15,12 +15,20 @@ use nom::{
|
|||
branch::alt,
|
||||
bytes::complete::tag_no_case,
|
||||
combinator::cut,
|
||||
combinator::opt,
|
||||
multi::{many0, separated_list1},
|
||||
sequence::tuple,
|
||||
Err,
|
||||
};
|
||||
|
||||
pub fn user(i: &str) -> IResult<&str, DefineUserStatement> {
|
||||
let (i, _) = tag_no_case("USER")(i)?;
|
||||
#[cfg(feature = "sql2")]
|
||||
let (i, if_not_exists) = opt(tuple((
|
||||
shouldbespace,
|
||||
tag_no_case("IF"),
|
||||
cut(tuple((shouldbespace, tag_no_case("NOT"), shouldbespace, tag_no_case("EXISTS")))),
|
||||
)))(i)?;
|
||||
let (i, _) = shouldbespace(i)?;
|
||||
let (i, (name, base, opts)) = cut(|i| {
|
||||
let (i, name) = ident(i)?;
|
||||
|
@ -38,6 +46,12 @@ pub fn user(i: &str) -> IResult<&str, DefineUserStatement> {
|
|||
base,
|
||||
vec!["Viewer".into()], // New users get the viewer role by default
|
||||
);
|
||||
|
||||
#[cfg(feature = "sql2")]
|
||||
if if_not_exists.is_some() {
|
||||
res.if_not_exists = true;
|
||||
};
|
||||
|
||||
// Assign any defined options
|
||||
for opt in opts {
|
||||
match opt {
|
||||
|
|
|
@ -40,22 +40,51 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_namespace(&mut self) -> ParseResult<DefineNamespaceStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
let comment = self.eat(t!("COMMENT")).then(|| self.next_token_value()).transpose()?;
|
||||
Ok(DefineNamespaceStatement {
|
||||
let mut res = DefineNamespaceStatement {
|
||||
id: None,
|
||||
name,
|
||||
comment,
|
||||
})
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
loop {
|
||||
match self.peek_kind() {
|
||||
t!("COMMENT") => {
|
||||
self.pop_peek();
|
||||
res.comment = Some(self.next_token_value()?);
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn parse_define_database(&mut self) -> ParseResult<DefineDatabaseStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
let mut res = DefineDatabaseStatement {
|
||||
id: None,
|
||||
name,
|
||||
comment: None,
|
||||
changefeed: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
..Default::default()
|
||||
};
|
||||
loop {
|
||||
match self.peek_kind() {
|
||||
|
@ -75,6 +104,14 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_function(&mut self) -> ParseResult<DefineFunctionStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.parse_custom_function_name()?;
|
||||
let token = expected!(self, t!("(")).span;
|
||||
let mut args = Vec::new();
|
||||
|
@ -102,6 +139,8 @@ impl Parser<'_> {
|
|||
name,
|
||||
args,
|
||||
block,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -123,6 +162,14 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_user(&mut self) -> ParseResult<DefineUserStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
expected!(self, t!("ON"));
|
||||
let base = self.parse_base(false)?;
|
||||
|
@ -133,6 +180,11 @@ impl Parser<'_> {
|
|||
vec!["Viewer".into()], // New users get the viewer role by default
|
||||
);
|
||||
|
||||
#[cfg(feature = "sql2")]
|
||||
if if_not_exists {
|
||||
res.if_not_exists = true;
|
||||
}
|
||||
|
||||
loop {
|
||||
match self.peek_kind() {
|
||||
t!("COMMENT") => {
|
||||
|
@ -162,6 +214,14 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_token(&mut self) -> ParseResult<DefineTokenStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
expected!(self, t!("ON"));
|
||||
let base = self.parse_base(true)?;
|
||||
|
@ -169,6 +229,8 @@ impl Parser<'_> {
|
|||
let mut res = DefineTokenStatement {
|
||||
name,
|
||||
base,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -199,10 +261,20 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_scope(&mut self) -> ParseResult<DefineScopeStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
let mut res = DefineScopeStatement {
|
||||
name,
|
||||
code: DefineScopeStatement::random_code(),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -232,10 +304,20 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_param(&mut self) -> ParseResult<DefineParamStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value::<Param>()?.0;
|
||||
|
||||
let mut res = DefineParamStatement {
|
||||
name,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -260,10 +342,20 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_table(&mut self) -> ParseResult<DefineTableStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
let mut res = DefineTableStatement {
|
||||
name,
|
||||
permissions: Permissions::none(),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -315,6 +407,14 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_event(&mut self) -> ParseResult<DefineEventStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
expected!(self, t!("ON"));
|
||||
self.eat(t!("TABLE"));
|
||||
|
@ -323,6 +423,8 @@ impl Parser<'_> {
|
|||
let mut res = DefineEventStatement {
|
||||
name,
|
||||
what,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -350,6 +452,14 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_field(&mut self) -> ParseResult<DefineFieldStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.parse_local_idiom()?;
|
||||
expected!(self, t!("ON"));
|
||||
self.eat(t!("TABLE"));
|
||||
|
@ -358,6 +468,8 @@ impl Parser<'_> {
|
|||
let mut res = DefineFieldStatement {
|
||||
name,
|
||||
what,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -405,6 +517,14 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_index(&mut self) -> ParseResult<DefineIndexStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
expected!(self, t!("ON"));
|
||||
self.eat(t!("TABLE"));
|
||||
|
@ -413,6 +533,8 @@ impl Parser<'_> {
|
|||
let mut res = DefineIndexStatement {
|
||||
name,
|
||||
what,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -564,6 +686,14 @@ impl Parser<'_> {
|
|||
}
|
||||
|
||||
pub fn parse_define_analyzer(&mut self) -> ParseResult<DefineAnalyzerStatement> {
|
||||
#[cfg(feature = "sql2")]
|
||||
let if_not_exists = if self.eat(t!("IF")) {
|
||||
expected!(self, t!("NOT"));
|
||||
expected!(self, t!("EXISTS"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let name = self.next_token_value()?;
|
||||
let mut res = DefineAnalyzerStatement {
|
||||
name,
|
||||
|
@ -572,6 +702,8 @@ impl Parser<'_> {
|
|||
tokenizers: None,
|
||||
filters: None,
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists,
|
||||
};
|
||||
loop {
|
||||
match self.peek_kind() {
|
||||
|
|
|
@ -121,7 +121,9 @@ fn parse_define_namespace() {
|
|||
Statement::Define(DefineStatement::Namespace(DefineNamespaceStatement {
|
||||
id: None,
|
||||
name: Ident("a".to_string()),
|
||||
comment: Some(Strand("test".to_string()))
|
||||
comment: Some(Strand("test".to_string())),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -131,7 +133,9 @@ fn parse_define_namespace() {
|
|||
Statement::Define(DefineStatement::Namespace(DefineNamespaceStatement {
|
||||
id: None,
|
||||
name: Ident("a".to_string()),
|
||||
comment: None
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
@ -150,7 +154,9 @@ fn parse_define_database() {
|
|||
changefeed: Some(ChangeFeed {
|
||||
expiry: std::time::Duration::from_secs(60) * 10,
|
||||
store_original: true,
|
||||
})
|
||||
}),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -161,7 +167,9 @@ fn parse_define_database() {
|
|||
id: None,
|
||||
name: Ident("a".to_string()),
|
||||
comment: None,
|
||||
changefeed: None
|
||||
changefeed: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
@ -191,6 +199,8 @@ fn parse_define_function() {
|
|||
})]),
|
||||
comment: Some(Strand("test".to_string())),
|
||||
permissions: Permission::Full,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
@ -228,7 +238,9 @@ fn parse_define_token() {
|
|||
base: Base::Sc(Ident("b".to_string())),
|
||||
kind: Algorithm::EdDSA,
|
||||
code: "foo".to_string(),
|
||||
comment: Some(Strand("bar".to_string()))
|
||||
comment: Some(Strand("bar".to_string())),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
@ -272,7 +284,9 @@ fn parse_define_param() {
|
|||
.collect()
|
||||
)),
|
||||
comment: None,
|
||||
permissions: Permission::Specific(Value::Null)
|
||||
permissions: Permission::Specific(Value::Null),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
@ -319,6 +333,8 @@ fn parse_define_table() {
|
|||
store_original: true,
|
||||
}),
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
@ -337,6 +353,8 @@ fn parse_define_event() {
|
|||
when: Value::Null,
|
||||
then: Values(vec![Value::Null, Value::None]),
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
@ -374,7 +392,9 @@ fn parse_define_field() {
|
|||
create: Permission::Specific(Value::Bool(true)),
|
||||
select: Permission::Full,
|
||||
},
|
||||
comment: None
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
@ -421,7 +441,9 @@ fn parse_define_index() {
|
|||
postings_cache: 7,
|
||||
terms_cache: 8,
|
||||
}),
|
||||
comment: None
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -435,7 +457,9 @@ fn parse_define_index() {
|
|||
what: Ident("table".to_owned()),
|
||||
cols: Idioms(vec![Idiom(vec![Part::Field(Ident("a".to_owned()))]),]),
|
||||
index: Index::Uniq,
|
||||
comment: None
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -458,7 +482,9 @@ fn parse_define_index() {
|
|||
mtree_cache: 9,
|
||||
vector_type: VectorType::F64,
|
||||
}),
|
||||
comment: None
|
||||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
@ -491,6 +517,8 @@ fn parse_define_analyzer() {
|
|||
comment: None,
|
||||
#[cfg(feature = "sql2")]
|
||||
function: Some(Ident("foo::bar".to_string())),
|
||||
#[cfg(feature = "sql2")]
|
||||
if_not_exists: false,
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -151,11 +151,13 @@ fn statements() -> Vec<Statement> {
|
|||
id: None,
|
||||
name: Ident("a".to_string()),
|
||||
comment: Some(Strand("test".to_string())),
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Namespace(DefineNamespaceStatement {
|
||||
id: None,
|
||||
name: Ident("a".to_string()),
|
||||
comment: None,
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Database(DefineDatabaseStatement {
|
||||
id: None,
|
||||
|
@ -165,12 +167,14 @@ fn statements() -> Vec<Statement> {
|
|||
expiry: std::time::Duration::from_secs(60) * 10,
|
||||
store_original: false,
|
||||
}),
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Database(DefineDatabaseStatement {
|
||||
id: None,
|
||||
name: Ident("a".to_string()),
|
||||
comment: None,
|
||||
changefeed: None,
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Function(DefineFunctionStatement {
|
||||
name: Ident("foo::bar".to_string()),
|
||||
|
@ -184,6 +188,7 @@ fn statements() -> Vec<Statement> {
|
|||
})]),
|
||||
comment: Some(Strand("test".to_string())),
|
||||
permissions: Permission::Full,
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Token(DefineTokenStatement {
|
||||
name: Ident("a".to_string()),
|
||||
|
@ -191,6 +196,7 @@ fn statements() -> Vec<Statement> {
|
|||
kind: Algorithm::EdDSA,
|
||||
code: "foo".to_string(),
|
||||
comment: Some(Strand("bar".to_string())),
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Param(DefineParamStatement {
|
||||
name: Ident("a".to_string()),
|
||||
|
@ -204,6 +210,7 @@ fn statements() -> Vec<Statement> {
|
|||
)),
|
||||
comment: None,
|
||||
permissions: Permission::Specific(Value::Null),
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Table(DefineTableStatement {
|
||||
id: None,
|
||||
|
@ -239,6 +246,7 @@ fn statements() -> Vec<Statement> {
|
|||
store_original: false,
|
||||
}),
|
||||
comment: None,
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Event(DefineEventStatement {
|
||||
name: Ident("event".to_owned()),
|
||||
|
@ -246,6 +254,7 @@ fn statements() -> Vec<Statement> {
|
|||
when: Value::Null,
|
||||
then: Values(vec![Value::Null, Value::None]),
|
||||
comment: None,
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Field(DefineFieldStatement {
|
||||
name: Idiom(vec![
|
||||
|
@ -271,6 +280,7 @@ fn statements() -> Vec<Statement> {
|
|||
select: Permission::Full,
|
||||
},
|
||||
comment: None,
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Index(DefineIndexStatement {
|
||||
name: Ident("index".to_owned()),
|
||||
|
@ -296,6 +306,7 @@ fn statements() -> Vec<Statement> {
|
|||
terms_cache: 8,
|
||||
}),
|
||||
comment: None,
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Index(DefineIndexStatement {
|
||||
name: Ident("index".to_owned()),
|
||||
|
@ -303,6 +314,7 @@ fn statements() -> Vec<Statement> {
|
|||
cols: Idioms(vec![Idiom(vec![Part::Field(Ident("a".to_owned()))])]),
|
||||
index: Index::Uniq,
|
||||
comment: None,
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Index(DefineIndexStatement {
|
||||
name: Ident("index".to_owned()),
|
||||
|
@ -319,6 +331,7 @@ fn statements() -> Vec<Statement> {
|
|||
vector_type: VectorType::F64,
|
||||
}),
|
||||
comment: None,
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Define(DefineStatement::Analyzer(DefineAnalyzerStatement {
|
||||
name: Ident("ana".to_owned()),
|
||||
|
@ -338,6 +351,7 @@ fn statements() -> Vec<Statement> {
|
|||
]),
|
||||
function: Some(Ident("foo::bar".to_string())),
|
||||
comment: None,
|
||||
if_not_exists: false,
|
||||
})),
|
||||
Statement::Delete(DeleteStatement {
|
||||
only: true,
|
||||
|
|
|
@ -2118,3 +2118,495 @@ async fn define_statement_table_permissions() -> Result<(), Error> {
|
|||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_analyzer_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE ANALYZER example_blank TOKENIZERS blank;
|
||||
DEFINE ANALYZER example_blank TOKENIZERS blank;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_analyzer_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE ANALYZER IF NOT EXISTS example TOKENIZERS blank;
|
||||
DEFINE ANALYZER IF NOT EXISTS example TOKENIZERS blank;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::AzAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_database_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE DATABASE example;
|
||||
DEFINE DATABASE example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_database_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE DATABASE IF NOT EXISTS example;
|
||||
DEFINE DATABASE IF NOT EXISTS example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::DbAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_event_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE EVENT example ON example THEN {};
|
||||
DEFINE EVENT example ON example THEN {};
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_event_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE EVENT IF NOT EXISTS example ON example THEN {};
|
||||
DEFINE EVENT IF NOT EXISTS example ON example THEN {};
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::EvAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_field_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE FIELD example ON example;
|
||||
DEFINE FIELD example ON example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_field_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE FIELD IF NOT EXISTS example ON example;
|
||||
DEFINE FIELD IF NOT EXISTS example ON example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::FdAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_function_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE FUNCTION fn::example() {};
|
||||
DEFINE FUNCTION fn::example() {};
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_function_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE FUNCTION IF NOT EXISTS fn::example() {};
|
||||
DEFINE FUNCTION IF NOT EXISTS fn::example() {};
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::FcAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_index_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE INDEX example ON example FIELDS example;
|
||||
DEFINE INDEX example ON example FIELDS example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_index_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE INDEX IF NOT EXISTS example ON example FIELDS example;
|
||||
DEFINE INDEX IF NOT EXISTS example ON example FIELDS example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::IxAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_namespace_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE NAMESPACE example;
|
||||
DEFINE NAMESPACE example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_namespace_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE NAMESPACE IF NOT EXISTS example;
|
||||
DEFINE NAMESPACE IF NOT EXISTS example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::NsAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_param_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE PARAM $example VALUE 123;
|
||||
DEFINE PARAM $example VALUE 123;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_param_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE PARAM IF NOT EXISTS $example VALUE 123;
|
||||
DEFINE PARAM IF NOT EXISTS $example VALUE 123;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::PaAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_scope_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE SCOPE example;
|
||||
DEFINE SCOPE example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_scope_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE SCOPE IF NOT EXISTS example;
|
||||
DEFINE SCOPE IF NOT EXISTS example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::ScAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_table_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE TABLE example;
|
||||
DEFINE TABLE example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_table_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE TABLE IF NOT EXISTS example;
|
||||
DEFINE TABLE IF NOT EXISTS example;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::TbAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_token_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE TOKEN example ON SCOPE example TYPE HS512 VALUE \"example\";
|
||||
DEFINE TOKEN example ON SCOPE example TYPE HS512 VALUE \"example\";
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_token_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE TOKEN IF NOT EXISTS example ON SCOPE example TYPE HS512 VALUE \"example\";
|
||||
DEFINE TOKEN IF NOT EXISTS example ON SCOPE example TYPE HS512 VALUE \"example\";
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::StAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redefining_existing_user_should_not_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE USER example ON ROOT PASSWORD \"example\" ROLES OWNER;
|
||||
DEFINE USER example ON ROOT PASSWORD \"example\" ROLES OWNER;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "sql2")]
|
||||
async fn redefining_existing_user_with_if_not_exists_should_error() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE USER IF NOT EXISTS example ON ROOT PASSWORD \"example\" ROLES OWNER;
|
||||
DEFINE USER IF NOT EXISTS example ON ROOT PASSWORD \"example\" ROLES OWNER;
|
||||
";
|
||||
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(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(tmp, Value::None);
|
||||
//
|
||||
let tmp = res.remove(0).result.unwrap_err();
|
||||
assert!(matches!(tmp, Error::UserRootAlreadyExists { .. }),);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue