From ebc140e8ad3078b4c9cbbb35a5ae6e88088a4cbb Mon Sep 17 00:00:00 2001 From: Micha de Vries Date: Tue, 6 Aug 2024 15:10:58 +0100 Subject: [PATCH] `DEFINE @kind OVERWRITE` (#4465) --- core/src/sql/statements/define/access.rs | 16 ++- core/src/sql/statements/define/analyzer.rs | 10 +- core/src/sql/statements/define/database.rs | 10 +- core/src/sql/statements/define/event.rs | 10 +- core/src/sql/statements/define/field.rs | 11 +- core/src/sql/statements/define/function.rs | 10 +- core/src/sql/statements/define/index.rs | 10 +- core/src/sql/statements/define/mod.rs | 2 +- core/src/sql/statements/define/model.rs | 10 +- core/src/sql/statements/define/namespace.rs | 10 +- core/src/sql/statements/define/param.rs | 10 +- core/src/sql/statements/define/table.rs | 10 +- core/src/sql/statements/define/user.rs | 17 ++- .../serde/ser/statement/define/access.rs | 5 + .../serde/ser/statement/define/analyzer.rs | 5 + .../serde/ser/statement/define/database.rs | 5 + .../value/serde/ser/statement/define/event.rs | 5 + .../value/serde/ser/statement/define/field.rs | 5 + .../serde/ser/statement/define/function.rs | 5 + .../value/serde/ser/statement/define/index.rs | 5 + .../serde/ser/statement/define/namespace.rs | 5 + .../value/serde/ser/statement/define/param.rs | 5 + .../value/serde/ser/statement/define/table.rs | 5 + .../value/serde/ser/statement/define/user.rs | 5 + core/src/syn/lexer/keywords.rs | 1 + core/src/syn/parser/stmt/define.rs | 120 ++++++++++++------ core/src/syn/parser/test/stmt.rs | 33 +++++ core/src/syn/parser/test/streaming.rs | 14 ++ core/src/syn/token/keyword.rs | 1 + lib/tests/define.rs | 22 ++++ 30 files changed, 314 insertions(+), 68 deletions(-) diff --git a/core/src/sql/statements/define/access.rs b/core/src/sql/statements/define/access.rs index d0d0f1ce..801280e6 100644 --- a/core/src/sql/statements/define/access.rs +++ b/core/src/sql/statements/define/access.rs @@ -12,7 +12,7 @@ use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; -#[revisioned(revision = 2)] +#[revisioned(revision = 3)] #[derive(Clone, Default, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -25,6 +25,8 @@ pub struct DefineAccessStatement { pub duration: AccessDuration, pub comment: Option, pub if_not_exists: bool, + #[revision(start = 3)] + pub overwrite: bool, } impl DefineAccessStatement { @@ -70,7 +72,7 @@ impl DefineAccessStatement { if txn.get_root_access(&self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::AccessRootAlreadyExists { value: self.name.to_string(), }); @@ -83,6 +85,7 @@ impl DefineAccessStatement { DefineAccessStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -99,7 +102,7 @@ impl DefineAccessStatement { if txn.get_ns_access(opt.ns()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::AccessNsAlreadyExists { value: self.name.to_string(), ns: opt.ns()?.into(), @@ -114,6 +117,7 @@ impl DefineAccessStatement { DefineAccessStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -130,7 +134,7 @@ impl DefineAccessStatement { if txn.get_db_access(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::AccessDbAlreadyExists { value: self.name.to_string(), ns: opt.ns()?.into(), @@ -147,6 +151,7 @@ impl DefineAccessStatement { DefineAccessStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -168,6 +173,9 @@ impl Display for DefineAccessStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } // The specific access method definition is displayed by AccessType write!(f, " {} ON {} TYPE {}", self.name, self.base, self.kind)?; // The additional authentication clause diff --git a/core/src/sql/statements/define/analyzer.rs b/core/src/sql/statements/define/analyzer.rs index de2fa16f..21c71b99 100644 --- a/core/src/sql/statements/define/analyzer.rs +++ b/core/src/sql/statements/define/analyzer.rs @@ -10,7 +10,7 @@ use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; -#[revisioned(revision = 3)] +#[revisioned(revision = 4)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -23,6 +23,8 @@ pub struct DefineAnalyzerStatement { pub comment: Option, #[revision(start = 3)] pub if_not_exists: bool, + #[revision(start = 4)] + pub overwrite: bool, } impl DefineAnalyzerStatement { @@ -40,7 +42,7 @@ impl DefineAnalyzerStatement { if txn.get_db_analyzer(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::AzAlreadyExists { value: self.name.to_string(), }); @@ -55,6 +57,7 @@ impl DefineAnalyzerStatement { DefineAnalyzerStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -72,6 +75,9 @@ impl Display for DefineAnalyzerStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!(f, " {}", self.name)?; if let Some(ref i) = self.function { write!(f, " FUNCTION fn::{i}")? diff --git a/core/src/sql/statements/define/database.rs b/core/src/sql/statements/define/database.rs index 8d08134f..9949841c 100644 --- a/core/src/sql/statements/define/database.rs +++ b/core/src/sql/statements/define/database.rs @@ -10,7 +10,7 @@ use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; -#[revisioned(revision = 2)] +#[revisioned(revision = 3)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -21,6 +21,8 @@ pub struct DefineDatabaseStatement { pub changefeed: Option, #[revision(start = 2)] pub if_not_exists: bool, + #[revision(start = 3)] + pub overwrite: bool, } impl DefineDatabaseStatement { @@ -39,7 +41,7 @@ impl DefineDatabaseStatement { if txn.get_db(opt.ns()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::DbAlreadyExists { value: self.name.to_string(), }); @@ -58,6 +60,7 @@ impl DefineDatabaseStatement { }, // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -75,6 +78,9 @@ impl Display for DefineDatabaseStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!(f, " {}", self.name)?; if let Some(ref v) = self.comment { write!(f, " COMMENT {v}")? diff --git a/core/src/sql/statements/define/event.rs b/core/src/sql/statements/define/event.rs index 45a76e77..694b3b8e 100644 --- a/core/src/sql/statements/define/event.rs +++ b/core/src/sql/statements/define/event.rs @@ -10,7 +10,7 @@ use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; -#[revisioned(revision = 2)] +#[revisioned(revision = 3)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -22,6 +22,8 @@ pub struct DefineEventStatement { pub comment: Option, #[revision(start = 2)] pub if_not_exists: bool, + #[revision(start = 3)] + pub overwrite: bool, } impl DefineEventStatement { @@ -40,7 +42,7 @@ impl DefineEventStatement { if txn.get_tb_event(opt.ns()?, opt.db()?, &self.what, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::EvAlreadyExists { value: self.name.to_string(), }); @@ -56,6 +58,7 @@ impl DefineEventStatement { DefineEventStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -73,6 +76,9 @@ impl Display for DefineEventStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!(f, " {} ON {} WHEN {} THEN {}", self.name, self.what, self.when, self.then)?; if let Some(ref v) = self.comment { write!(f, " COMMENT {v}")? diff --git a/core/src/sql/statements/define/field.rs b/core/src/sql/statements/define/field.rs index 9a5b0447..75ddff0c 100644 --- a/core/src/sql/statements/define/field.rs +++ b/core/src/sql/statements/define/field.rs @@ -14,7 +14,7 @@ use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display, Write}; -#[revisioned(revision = 3)] +#[revisioned(revision = 4)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -32,6 +32,8 @@ pub struct DefineFieldStatement { pub comment: Option, #[revision(start = 3)] pub if_not_exists: bool, + #[revision(start = 4)] + pub overwrite: bool, } impl DefineFieldStatement { @@ -55,7 +57,7 @@ impl DefineFieldStatement { if txn.get_tb_field(ns, db, &self.what, &fd).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::FdAlreadyExists { value: fd, }); @@ -71,6 +73,7 @@ impl DefineFieldStatement { DefineFieldStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -97,6 +100,7 @@ impl DefineFieldStatement { DefineFieldStatement { kind: Some(cur_kind), if_not_exists: false, + overwrite: false, ..existing.clone() } } else { @@ -189,6 +193,9 @@ impl Display for DefineFieldStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!(f, " {} ON {}", self.name, self.what)?; if self.flex { write!(f, " FLEXIBLE")? diff --git a/core/src/sql/statements/define/function.rs b/core/src/sql/statements/define/function.rs index 43d3bd3d..c87f1029 100644 --- a/core/src/sql/statements/define/function.rs +++ b/core/src/sql/statements/define/function.rs @@ -11,7 +11,7 @@ use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display, Write}; -#[revisioned(revision = 2)] +#[revisioned(revision = 3)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -23,6 +23,8 @@ pub struct DefineFunctionStatement { pub permissions: Permission, #[revision(start = 2)] pub if_not_exists: bool, + #[revision(start = 3)] + pub overwrite: bool, } impl DefineFunctionStatement { @@ -41,7 +43,7 @@ impl DefineFunctionStatement { if txn.get_db_function(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::FcAlreadyExists { value: self.name.to_string(), }); @@ -56,6 +58,7 @@ impl DefineFunctionStatement { DefineFunctionStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -73,6 +76,9 @@ impl fmt::Display for DefineFunctionStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!(f, " fn::{}(", self.name.0)?; for (i, (name, kind)) in self.args.iter().enumerate() { if i > 0 { diff --git a/core/src/sql/statements/define/index.rs b/core/src/sql/statements/define/index.rs index 6ab7488d..18816a20 100644 --- a/core/src/sql/statements/define/index.rs +++ b/core/src/sql/statements/define/index.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; use std::sync::Arc; -#[revisioned(revision = 2)] +#[revisioned(revision = 3)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -25,6 +25,8 @@ pub struct DefineIndexStatement { pub comment: Option, #[revision(start = 2)] pub if_not_exists: bool, + #[revision(start = 3)] + pub overwrite: bool, } impl DefineIndexStatement { @@ -44,7 +46,7 @@ impl DefineIndexStatement { if txn.get_tb_index(opt.ns()?, opt.db()?, &self.what, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::IxAlreadyExists { value: self.name.to_string(), }); @@ -80,6 +82,7 @@ impl DefineIndexStatement { DefineIndexStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -106,6 +109,9 @@ impl Display for DefineIndexStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!(f, " {} ON {} FIELDS {}", self.name, self.what, self.cols)?; if Index::Idx != self.index { write!(f, " {}", self.index)?; diff --git a/core/src/sql/statements/define/mod.rs b/core/src/sql/statements/define/mod.rs index 64d3b8c1..f2c4e12c 100644 --- a/core/src/sql/statements/define/mod.rs +++ b/core/src/sql/statements/define/mod.rs @@ -116,6 +116,6 @@ mod tests { ..Default::default() }); let enc: Vec = stm.into(); - assert_eq!(12, enc.len()); + assert_eq!(13, enc.len()); } } diff --git a/core/src/sql/statements/define/model.rs b/core/src/sql/statements/define/model.rs index 2f7439ae..c81d1ec1 100644 --- a/core/src/sql/statements/define/model.rs +++ b/core/src/sql/statements/define/model.rs @@ -11,7 +11,7 @@ use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Write}; -#[revisioned(revision = 2)] +#[revisioned(revision = 3)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -23,6 +23,8 @@ pub struct DefineModelStatement { pub permissions: Permission, #[revision(start = 2)] pub if_not_exists: bool, + #[revision(start = 3)] + pub overwrite: bool, } impl DefineModelStatement { @@ -41,7 +43,7 @@ impl DefineModelStatement { if txn.get_db_model(opt.ns()?, opt.db()?, &self.name, &self.version).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::MlAlreadyExists { value: self.name.to_string(), }); @@ -56,6 +58,7 @@ impl DefineModelStatement { DefineModelStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -73,6 +76,9 @@ impl fmt::Display for DefineModelStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!(f, " ml::{}<{}>", self.name, self.version)?; if let Some(comment) = self.comment.as_ref() { write!(f, " COMMENT {}", comment)?; diff --git a/core/src/sql/statements/define/namespace.rs b/core/src/sql/statements/define/namespace.rs index 6a23f78f..52986e0f 100644 --- a/core/src/sql/statements/define/namespace.rs +++ b/core/src/sql/statements/define/namespace.rs @@ -10,7 +10,7 @@ use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; -#[revisioned(revision = 2)] +#[revisioned(revision = 3)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -20,6 +20,8 @@ pub struct DefineNamespaceStatement { pub comment: Option, #[revision(start = 2)] pub if_not_exists: bool, + #[revision(start = 3)] + pub overwrite: bool, } impl DefineNamespaceStatement { @@ -38,7 +40,7 @@ impl DefineNamespaceStatement { if txn.get_ns(&self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::NsAlreadyExists { value: self.name.to_string(), }); @@ -56,6 +58,7 @@ impl DefineNamespaceStatement { }, // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -73,6 +76,9 @@ impl Display for DefineNamespaceStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!(f, " {}", self.name)?; if let Some(ref v) = self.comment { write!(f, " COMMENT {v}")? diff --git a/core/src/sql/statements/define/param.rs b/core/src/sql/statements/define/param.rs index 53b2f925..74f840fb 100644 --- a/core/src/sql/statements/define/param.rs +++ b/core/src/sql/statements/define/param.rs @@ -12,7 +12,7 @@ use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display, Write}; -#[revisioned(revision = 2)] +#[revisioned(revision = 3)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -23,6 +23,8 @@ pub struct DefineParamStatement { pub permissions: Permission, #[revision(start = 2)] pub if_not_exists: bool, + #[revision(start = 3)] + pub overwrite: bool, } impl DefineParamStatement { @@ -42,7 +44,7 @@ impl DefineParamStatement { if txn.get_db_param(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::PaAlreadyExists { value: self.name.to_string(), }); @@ -59,6 +61,7 @@ impl DefineParamStatement { value: self.value.compute(stk, ctx, opt, doc).await?, // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -76,6 +79,9 @@ impl Display for DefineParamStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!(f, " ${} VALUE {}", self.name, self.value)?; if let Some(ref v) = self.comment { write!(f, " COMMENT {v}")? diff --git a/core/src/sql/statements/define/table.rs b/core/src/sql/statements/define/table.rs index f1222671..9d649e79 100644 --- a/core/src/sql/statements/define/table.rs +++ b/core/src/sql/statements/define/table.rs @@ -20,7 +20,7 @@ use serde::{Deserialize, Serialize}; use std::fmt::{self, Display, Write}; use std::sync::Arc; -#[revisioned(revision = 3)] +#[revisioned(revision = 4)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -37,6 +37,8 @@ pub struct DefineTableStatement { pub if_not_exists: bool, #[revision(start = 3)] pub kind: TableType, + #[revision(start = 4)] + pub overwrite: bool, } impl DefineTableStatement { @@ -55,7 +57,7 @@ impl DefineTableStatement { if txn.get_tb(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::TbAlreadyExists { value: self.name.to_string(), }); @@ -73,6 +75,7 @@ impl DefineTableStatement { }, // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }; txn.set(key, &dt).await?; @@ -173,6 +176,9 @@ impl Display for DefineTableStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!(f, " {}", self.name)?; write!(f, " TYPE")?; match &self.kind { diff --git a/core/src/sql/statements/define/user.rs b/core/src/sql/statements/define/user.rs index dfe9a27b..0bbc599a 100644 --- a/core/src/sql/statements/define/user.rs +++ b/core/src/sql/statements/define/user.rs @@ -17,7 +17,7 @@ use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; -#[revisioned(revision = 3)] +#[revisioned(revision = 4)] #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -32,6 +32,8 @@ pub struct DefineUserStatement { pub comment: Option, #[revision(start = 2)] pub if_not_exists: bool, + #[revision(start = 4)] + pub overwrite: bool, } impl From<(Base, &str, &str, &str)> for DefineUserStatement { @@ -52,6 +54,7 @@ impl From<(Base, &str, &str, &str)> for DefineUserStatement { duration: UserDuration::default(), comment: None, if_not_exists: false, + overwrite: false, } } } @@ -114,7 +117,7 @@ impl DefineUserStatement { if txn.get_root_user(&self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::UserRootAlreadyExists { value: self.name.to_string(), }); @@ -127,6 +130,7 @@ impl DefineUserStatement { DefineUserStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -143,7 +147,7 @@ impl DefineUserStatement { if txn.get_ns_user(opt.ns()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::UserNsAlreadyExists { value: self.name.to_string(), ns: opt.ns()?.into(), @@ -158,6 +162,7 @@ impl DefineUserStatement { DefineUserStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -174,7 +179,7 @@ impl DefineUserStatement { if txn.get_db_user(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); - } else { + } else if !self.overwrite { return Err(Error::UserDbAlreadyExists { value: self.name.to_string(), ns: opt.ns()?.into(), @@ -191,6 +196,7 @@ impl DefineUserStatement { DefineUserStatement { // Don't persist the `IF NOT EXISTS` clause to schema if_not_exists: false, + overwrite: false, ..self.clone() }, ) @@ -212,6 +218,9 @@ impl Display for DefineUserStatement { if self.if_not_exists { write!(f, " IF NOT EXISTS")? } + if self.overwrite { + write!(f, " OVERWRITE")? + } write!( f, " {} ON {} PASSHASH {} ROLES {}", diff --git a/core/src/sql/value/serde/ser/statement/define/access.rs b/core/src/sql/value/serde/ser/statement/define/access.rs index cf2009cb..cd85810b 100644 --- a/core/src/sql/value/serde/ser/statement/define/access.rs +++ b/core/src/sql/value/serde/ser/statement/define/access.rs @@ -50,6 +50,7 @@ pub struct SerializeDefineAccessStatement { duration: AccessDuration, comment: Option, if_not_exists: bool, + overwrite: bool, } impl serde::ser::SerializeStruct for SerializeDefineAccessStatement { @@ -82,6 +83,9 @@ impl serde::ser::SerializeStruct for SerializeDefineAccessStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineAccessStatement::{key}`" @@ -100,6 +104,7 @@ impl serde::ser::SerializeStruct for SerializeDefineAccessStatement { duration: self.duration, comment: self.comment, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/sql/value/serde/ser/statement/define/analyzer.rs b/core/src/sql/value/serde/ser/statement/define/analyzer.rs index f6ff7629..f722e5af 100644 --- a/core/src/sql/value/serde/ser/statement/define/analyzer.rs +++ b/core/src/sql/value/serde/ser/statement/define/analyzer.rs @@ -46,6 +46,7 @@ pub struct SerializeDefineAnalyzerStatement { filters: Option>, comment: Option, if_not_exists: bool, + overwrite: bool, } impl serde::ser::SerializeStruct for SerializeDefineAnalyzerStatement { @@ -75,6 +76,9 @@ impl serde::ser::SerializeStruct for SerializeDefineAnalyzerStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineAnalyzerStatement::{key}`" @@ -92,6 +96,7 @@ impl serde::ser::SerializeStruct for SerializeDefineAnalyzerStatement { filters: self.filters, comment: self.comment, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/sql/value/serde/ser/statement/define/database.rs b/core/src/sql/value/serde/ser/statement/define/database.rs index 143da665..9bebf2f4 100644 --- a/core/src/sql/value/serde/ser/statement/define/database.rs +++ b/core/src/sql/value/serde/ser/statement/define/database.rs @@ -44,6 +44,7 @@ pub struct SerializeDefineDatabaseStatement { id: Option, comment: Option, if_not_exists: bool, + overwrite: bool, } impl serde::ser::SerializeStruct for SerializeDefineDatabaseStatement { @@ -70,6 +71,9 @@ impl serde::ser::SerializeStruct for SerializeDefineDatabaseStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineDatabaseStatement::{key}`" @@ -86,6 +90,7 @@ impl serde::ser::SerializeStruct for SerializeDefineDatabaseStatement { id: self.id, comment: self.comment, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/sql/value/serde/ser/statement/define/event.rs b/core/src/sql/value/serde/ser/statement/define/event.rs index 2fb747d1..897fd59f 100644 --- a/core/src/sql/value/serde/ser/statement/define/event.rs +++ b/core/src/sql/value/serde/ser/statement/define/event.rs @@ -46,6 +46,7 @@ pub struct SerializeDefineEventStatement { then: Values, comment: Option, if_not_exists: bool, + overwrite: bool, } impl serde::ser::SerializeStruct for SerializeDefineEventStatement { @@ -75,6 +76,9 @@ impl serde::ser::SerializeStruct for SerializeDefineEventStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineEventStatement::{key}`" @@ -92,6 +96,7 @@ impl serde::ser::SerializeStruct for SerializeDefineEventStatement { then: self.then, comment: self.comment, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/sql/value/serde/ser/statement/define/field.rs b/core/src/sql/value/serde/ser/statement/define/field.rs index 53952423..2e9e8aee 100644 --- a/core/src/sql/value/serde/ser/statement/define/field.rs +++ b/core/src/sql/value/serde/ser/statement/define/field.rs @@ -53,6 +53,7 @@ pub struct SerializeDefineFieldStatement { permissions: Permissions, comment: Option, if_not_exists: bool, + overwrite: bool, } impl serde::ser::SerializeStruct for SerializeDefineFieldStatement { @@ -97,6 +98,9 @@ impl serde::ser::SerializeStruct for SerializeDefineFieldStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineFieldStatement::{key}`" @@ -119,6 +123,7 @@ impl serde::ser::SerializeStruct for SerializeDefineFieldStatement { permissions: self.permissions, comment: self.comment, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/sql/value/serde/ser/statement/define/function.rs b/core/src/sql/value/serde/ser/statement/define/function.rs index 0386ea52..6aa81f43 100644 --- a/core/src/sql/value/serde/ser/statement/define/function.rs +++ b/core/src/sql/value/serde/ser/statement/define/function.rs @@ -47,6 +47,7 @@ pub struct SerializeDefineFunctionStatement { comment: Option, permissions: Permission, if_not_exists: bool, + overwrite: bool, } impl serde::ser::SerializeStruct for SerializeDefineFunctionStatement { @@ -76,6 +77,9 @@ impl serde::ser::SerializeStruct for SerializeDefineFunctionStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineFunctionStatement::{key}`" @@ -93,6 +97,7 @@ impl serde::ser::SerializeStruct for SerializeDefineFunctionStatement { comment: self.comment, permissions: self.permissions, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/sql/value/serde/ser/statement/define/index.rs b/core/src/sql/value/serde/ser/statement/define/index.rs index 70bb94db..a394305d 100644 --- a/core/src/sql/value/serde/ser/statement/define/index.rs +++ b/core/src/sql/value/serde/ser/statement/define/index.rs @@ -46,6 +46,7 @@ pub struct SerializeDefineIndexStatement { index: Index, comment: Option, if_not_exists: bool, + overwrite: bool, } impl serde::ser::SerializeStruct for SerializeDefineIndexStatement { @@ -75,6 +76,9 @@ impl serde::ser::SerializeStruct for SerializeDefineIndexStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineIndexStatement::{key}`" @@ -92,6 +96,7 @@ impl serde::ser::SerializeStruct for SerializeDefineIndexStatement { index: self.index, comment: self.comment, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/sql/value/serde/ser/statement/define/namespace.rs b/core/src/sql/value/serde/ser/statement/define/namespace.rs index 3f367058..63ed0faa 100644 --- a/core/src/sql/value/serde/ser/statement/define/namespace.rs +++ b/core/src/sql/value/serde/ser/statement/define/namespace.rs @@ -42,6 +42,7 @@ pub struct SerializeDefineNamespaceStatement { id: Option, comment: Option, if_not_exists: bool, + overwrite: bool, } impl serde::ser::SerializeStruct for SerializeDefineNamespaceStatement { @@ -65,6 +66,9 @@ impl serde::ser::SerializeStruct for SerializeDefineNamespaceStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineNamespaceStatement::{key}`" @@ -80,6 +84,7 @@ impl serde::ser::SerializeStruct for SerializeDefineNamespaceStatement { id: self.id, comment: self.comment, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/sql/value/serde/ser/statement/define/param.rs b/core/src/sql/value/serde/ser/statement/define/param.rs index 25309f29..7f3530f1 100644 --- a/core/src/sql/value/serde/ser/statement/define/param.rs +++ b/core/src/sql/value/serde/ser/statement/define/param.rs @@ -45,6 +45,7 @@ pub struct SerializeDefineParamStatement { comment: Option, permissions: Permission, if_not_exists: bool, + overwrite: bool, } impl serde::ser::SerializeStruct for SerializeDefineParamStatement { @@ -71,6 +72,9 @@ impl serde::ser::SerializeStruct for SerializeDefineParamStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineParamStatement::{key}`" @@ -87,6 +91,7 @@ impl serde::ser::SerializeStruct for SerializeDefineParamStatement { comment: self.comment, permissions: self.permissions, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/sql/value/serde/ser/statement/define/table.rs b/core/src/sql/value/serde/ser/statement/define/table.rs index b8ff41d1..1bbd988c 100644 --- a/core/src/sql/value/serde/ser/statement/define/table.rs +++ b/core/src/sql/value/serde/ser/statement/define/table.rs @@ -51,6 +51,7 @@ pub struct SerializeDefineTableStatement { changefeed: Option, comment: Option, if_not_exists: bool, + overwrite: bool, kind: TableType, } @@ -93,6 +94,9 @@ impl serde::ser::SerializeStruct for SerializeDefineTableStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineTableStatement::{key}`" @@ -114,6 +118,7 @@ impl serde::ser::SerializeStruct for SerializeDefineTableStatement { comment: self.comment, kind: self.kind, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/sql/value/serde/ser/statement/define/user.rs b/core/src/sql/value/serde/ser/statement/define/user.rs index 0a480540..610236c5 100644 --- a/core/src/sql/value/serde/ser/statement/define/user.rs +++ b/core/src/sql/value/serde/ser/statement/define/user.rs @@ -49,6 +49,7 @@ pub struct SerializeDefineUserStatement { duration: UserDuration, comment: Option, if_not_exists: bool, + overwrite: bool, } impl serde::ser::SerializeStruct for SerializeDefineUserStatement { @@ -84,6 +85,9 @@ impl serde::ser::SerializeStruct for SerializeDefineUserStatement { "if_not_exists" => { self.if_not_exists = value.serialize(ser::primitive::bool::Serializer.wrap())? } + "overwrite" => { + self.overwrite = value.serialize(ser::primitive::bool::Serializer.wrap())? + } key => { return Err(Error::custom(format!( "unexpected field `DefineUserStatement::{key}`" @@ -103,6 +107,7 @@ impl serde::ser::SerializeStruct for SerializeDefineUserStatement { duration: self.duration, comment: self.comment, if_not_exists: self.if_not_exists, + overwrite: self.overwrite, }) } } diff --git a/core/src/syn/lexer/keywords.rs b/core/src/syn/lexer/keywords.rs index c844d48b..73c32bf1 100644 --- a/core/src/syn/lexer/keywords.rs +++ b/core/src/syn/lexer/keywords.rs @@ -169,6 +169,7 @@ pub(crate) static KEYWORDS: phf::Map, TokenKind> = phf_map UniCase::ascii("OPTION") => TokenKind::Keyword(Keyword::Option), UniCase::ascii("ORDER") => TokenKind::Keyword(Keyword::Order), UniCase::ascii("ORIGINAL") => TokenKind::Keyword(Keyword::Original), + UniCase::ascii("OVERWRITE") => TokenKind::Keyword(Keyword::Overwrite), UniCase::ascii("PARALLEL") => TokenKind::Keyword(Keyword::Parallel), UniCase::ascii("PARAM") => TokenKind::Keyword(Keyword::Param), UniCase::ascii("PASSHASH") => TokenKind::Keyword(Keyword::Passhash), diff --git a/core/src/syn/parser/stmt/define.rs b/core/src/syn/parser/stmt/define.rs index 53f0abc9..ecb3c20c 100644 --- a/core/src/syn/parser/stmt/define.rs +++ b/core/src/syn/parser/stmt/define.rs @@ -55,18 +55,21 @@ impl Parser<'_> { } pub fn parse_define_namespace(&mut self) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value()?; let mut res = DefineNamespaceStatement { id: None, name, if_not_exists, + overwrite, ..Default::default() }; @@ -79,17 +82,20 @@ impl Parser<'_> { } pub fn parse_define_database(&mut self) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value()?; let mut res = DefineDatabaseStatement { name, if_not_exists, + overwrite, ..Default::default() }; loop { @@ -113,12 +119,14 @@ impl Parser<'_> { &mut self, ctx: &mut Stk, ) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.parse_custom_function_name()?; let token = expected!(self, t!("(")).span; @@ -148,6 +156,7 @@ impl Parser<'_> { args, block, if_not_exists, + overwrite, ..Default::default() }; @@ -169,12 +178,14 @@ impl Parser<'_> { } pub fn parse_define_user(&mut self) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value()?; expected!(self, t!("ON")); @@ -191,6 +202,10 @@ impl Parser<'_> { res.if_not_exists = true; } + if overwrite { + res.overwrite = true; + } + loop { match self.peek_kind() { t!("COMMENT") => { @@ -253,12 +268,14 @@ impl Parser<'_> { &mut self, stk: &mut Stk, ) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value()?; expected!(self, t!("ON")); @@ -269,6 +286,7 @@ impl Parser<'_> { name, base, if_not_exists, + overwrite, ..Default::default() }; @@ -377,12 +395,14 @@ impl Parser<'_> { // TODO(gguillemas): Deprecated in 2.0.0. Drop this in 3.0.0 in favor of DEFINE ACCESS pub fn parse_define_token(&mut self) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value()?; expected!(self, t!("ON")); @@ -392,6 +412,7 @@ impl Parser<'_> { name, base: base.clone(), if_not_exists, + overwrite, ..Default::default() }; @@ -491,18 +512,21 @@ impl Parser<'_> { &mut self, stk: &mut Stk, ) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value()?; let mut res = DefineAccessStatement { name, base: Base::Db, if_not_exists, + overwrite, ..Default::default() }; let mut ac = access_type::RecordAccess { @@ -537,18 +561,21 @@ impl Parser<'_> { } pub async fn parse_define_param(&mut self, ctx: &mut Stk) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value::()?.0; let mut res = DefineParamStatement { name, if_not_exists, + overwrite, ..Default::default() }; @@ -573,18 +600,21 @@ impl Parser<'_> { } pub async fn parse_define_table(&mut self, ctx: &mut Stk) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value()?; let mut res = DefineTableStatement { name, permissions: Permissions::none(), if_not_exists, + overwrite, ..Default::default() }; @@ -654,12 +684,14 @@ impl Parser<'_> { } pub async fn parse_define_event(&mut self, ctx: &mut Stk) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value()?; expected!(self, t!("ON")); @@ -670,6 +702,7 @@ impl Parser<'_> { name, what, if_not_exists, + overwrite, ..Default::default() }; @@ -697,12 +730,14 @@ impl Parser<'_> { } pub async fn parse_define_field(&mut self, ctx: &mut Stk) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.parse_local_idiom()?; expected!(self, t!("ON")); @@ -713,6 +748,7 @@ impl Parser<'_> { name, what, if_not_exists, + overwrite, ..Default::default() }; @@ -759,12 +795,14 @@ impl Parser<'_> { } pub fn parse_define_index(&mut self) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value()?; expected!(self, t!("ON")); @@ -776,6 +814,7 @@ impl Parser<'_> { what, if_not_exists, + overwrite, ..Default::default() }; @@ -1015,12 +1054,14 @@ impl Parser<'_> { } pub fn parse_define_analyzer(&mut self) -> ParseResult { - let if_not_exists = if self.eat(t!("IF")) { + let (if_not_exists, overwrite) = if self.eat(t!("IF")) { expected!(self, t!("NOT")); expected!(self, t!("EXISTS")); - true + (true, false) + } else if self.eat(t!("OVERWRITE")) { + (false, true) } else { - false + (false, false) }; let name = self.next_token_value()?; let mut res = DefineAnalyzerStatement { @@ -1032,6 +1073,7 @@ impl Parser<'_> { comment: None, if_not_exists, + overwrite, }; loop { match self.peek_kind() { diff --git a/core/src/syn/parser/test/stmt.rs b/core/src/syn/parser/test/stmt.rs index 1296dbb1..50e1392e 100644 --- a/core/src/syn/parser/test/stmt.rs +++ b/core/src/syn/parser/test/stmt.rs @@ -131,6 +131,7 @@ fn parse_define_namespace() { name: Ident("a".to_string()), comment: Some(Strand("test".to_string())), if_not_exists: false, + overwrite: false, })) ); @@ -142,6 +143,7 @@ fn parse_define_namespace() { name: Ident("a".to_string()), comment: None, if_not_exists: false, + overwrite: false, })) ) } @@ -162,6 +164,7 @@ fn parse_define_database() { store_diff: true, }), if_not_exists: false, + overwrite: false, })) ); @@ -174,6 +177,7 @@ fn parse_define_database() { comment: None, changefeed: None, if_not_exists: false, + overwrite: false, })) ) } @@ -204,6 +208,7 @@ fn parse_define_function() { comment: Some(Strand("test".to_string())), permissions: Permission::Full, if_not_exists: false, + overwrite: false, })) ) } @@ -375,6 +380,7 @@ fn parse_define_token() { }, comment: Some(Strand("bar".to_string())), if_not_exists: false, + overwrite: false, })), ) } @@ -451,6 +457,7 @@ fn parse_define_token_jwks() { }, comment: Some(Strand("bar".to_string())), if_not_exists: false, + overwrite: false, })), ) } @@ -577,6 +584,7 @@ fn parse_define_access_jwt_key() { }, comment: Some(Strand("bar".to_string())), if_not_exists: false, + overwrite: false, })), ) } @@ -611,6 +619,7 @@ fn parse_define_access_jwt_key() { }, comment: None, if_not_exists: false, + overwrite: false, })), ) } @@ -645,6 +654,7 @@ fn parse_define_access_jwt_key() { }, comment: None, if_not_exists: false, + overwrite: false, })), ) } @@ -679,6 +689,7 @@ fn parse_define_access_jwt_key() { }, comment: None, if_not_exists: false, + overwrite: false, })), ) } @@ -712,6 +723,7 @@ fn parse_define_access_jwt_key() { }, comment: None, if_not_exists: false, + overwrite: false, })), ) } @@ -746,6 +758,7 @@ fn parse_define_access_jwt_key() { }, comment: None, if_not_exists: false, + overwrite: false, })), ) } @@ -825,6 +838,7 @@ fn parse_define_access_jwt_key() { }, comment: Some(Strand("bar".to_string())), if_not_exists: false, + overwrite: false, })), ) } @@ -856,6 +870,7 @@ fn parse_define_access_jwt_key() { }, comment: Some(Strand("bar".to_string())), if_not_exists: false, + overwrite: false, })), ) } @@ -890,6 +905,7 @@ fn parse_define_access_jwt_jwks() { }, comment: Some(Strand("bar".to_string())), if_not_exists: false, + overwrite: false, })), ) } @@ -923,6 +939,7 @@ fn parse_define_access_jwt_jwks() { }, comment: None, if_not_exists: false, + overwrite: false, })), ) } @@ -955,6 +972,7 @@ fn parse_define_access_jwt_jwks() { }, comment: None, if_not_exists: false, + overwrite: false, })), ) } @@ -988,6 +1006,7 @@ fn parse_define_access_jwt_jwks() { }, comment: None, if_not_exists: false, + overwrite: false, })), ) } @@ -1020,6 +1039,7 @@ fn parse_define_access_jwt_jwks() { }, comment: None, if_not_exists: false, + overwrite: false, })), ) } @@ -1157,6 +1177,7 @@ fn parse_define_access_record() { }, comment: None, if_not_exists: false, + overwrite: false, })), ); } @@ -1197,6 +1218,7 @@ fn parse_define_access_record() { }, comment: None, if_not_exists: false, + overwrite: false, })), ); } @@ -1237,6 +1259,7 @@ fn parse_define_access_record() { }, comment: None, if_not_exists: false, + overwrite: false, })), ); } @@ -1309,6 +1332,7 @@ fn parse_define_access_record_with_jwt() { }, comment: Some(Strand("bar".to_string())), if_not_exists: false, + overwrite: false, })), ) } @@ -1334,6 +1358,7 @@ fn parse_define_param() { comment: None, permissions: Permission::Specific(Value::Null), if_not_exists: false, + overwrite: false, })) ); } @@ -1381,6 +1406,7 @@ fn parse_define_table() { }), comment: None, if_not_exists: false, + overwrite: false, kind: TableType::Any, })) ); @@ -1401,6 +1427,7 @@ fn parse_define_event() { then: Values(vec![Value::Null, Value::None]), comment: None, if_not_exists: false, + overwrite: false, })) ) } @@ -1439,6 +1466,7 @@ fn parse_define_field() { }, comment: None, if_not_exists: false, + overwrite: false, })) ) } @@ -1487,6 +1515,7 @@ fn parse_define_index() { }), comment: None, if_not_exists: false, + overwrite: false, })) ); @@ -1502,6 +1531,7 @@ fn parse_define_index() { index: Index::Uniq, comment: None, if_not_exists: false, + overwrite: false, })) ); @@ -1526,6 +1556,7 @@ fn parse_define_index() { }), comment: None, if_not_exists: false, + overwrite: false, })) ); @@ -1551,6 +1582,7 @@ fn parse_define_index() { }), comment: None, if_not_exists: false, + overwrite: false, })) ); } @@ -1583,6 +1615,7 @@ fn parse_define_analyzer() { comment: None, function: Some(Ident("foo::bar".to_string())), if_not_exists: false, + overwrite: false, })), ) } diff --git a/core/src/syn/parser/test/streaming.rs b/core/src/syn/parser/test/streaming.rs index 9905404d..de9a8291 100644 --- a/core/src/syn/parser/test/streaming.rs +++ b/core/src/syn/parser/test/streaming.rs @@ -156,12 +156,14 @@ fn statements() -> Vec { name: Ident("a".to_string()), comment: Some(Strand("test".to_string())), if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Namespace(DefineNamespaceStatement { id: None, name: Ident("a".to_string()), comment: None, if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Database(DefineDatabaseStatement { id: None, @@ -172,6 +174,7 @@ fn statements() -> Vec { store_diff: false, }), if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Database(DefineDatabaseStatement { id: None, @@ -179,6 +182,7 @@ fn statements() -> Vec { comment: None, changefeed: None, if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Function(DefineFunctionStatement { name: Ident("foo::bar".to_string()), @@ -193,6 +197,7 @@ fn statements() -> Vec { comment: Some(Strand("test".to_string())), permissions: Permission::Full, if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Access(DefineAccessStatement { name: Ident("a".to_string()), @@ -220,6 +225,7 @@ fn statements() -> Vec { }, comment: Some(Strand("bar".to_string())), if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Param(DefineParamStatement { name: Ident("a".to_string()), @@ -234,6 +240,7 @@ fn statements() -> Vec { comment: None, permissions: Permission::Specific(Value::Null), if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Table(DefineTableStatement { id: None, @@ -270,6 +277,7 @@ fn statements() -> Vec { }), comment: None, if_not_exists: false, + overwrite: false, kind: TableType::Any, })), Statement::Define(DefineStatement::Event(DefineEventStatement { @@ -279,6 +287,7 @@ fn statements() -> Vec { then: Values(vec![Value::Null, Value::None]), comment: None, if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Field(DefineFieldStatement { name: Idiom(vec![ @@ -305,6 +314,7 @@ fn statements() -> Vec { }, comment: None, if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Index(DefineIndexStatement { name: Ident("index".to_owned()), @@ -331,6 +341,7 @@ fn statements() -> Vec { }), comment: None, if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Index(DefineIndexStatement { name: Ident("index".to_owned()), @@ -339,6 +350,7 @@ fn statements() -> Vec { index: Index::Uniq, comment: None, if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Index(DefineIndexStatement { name: Ident("index".to_owned()), @@ -356,6 +368,7 @@ fn statements() -> Vec { }), comment: None, if_not_exists: false, + overwrite: false, })), Statement::Define(DefineStatement::Analyzer(DefineAnalyzerStatement { name: Ident("ana".to_owned()), @@ -376,6 +389,7 @@ fn statements() -> Vec { function: Some(Ident("foo::bar".to_string())), comment: None, if_not_exists: false, + overwrite: false, })), Statement::Delete(DeleteStatement { only: true, diff --git a/core/src/syn/token/keyword.rs b/core/src/syn/token/keyword.rs index 81b54723..eb61f106 100644 --- a/core/src/syn/token/keyword.rs +++ b/core/src/syn/token/keyword.rs @@ -128,6 +128,7 @@ keyword! { Option => "OPTION", Order => "ORDER", Original => "ORIGINAL", + Overwrite => "OVERWRITE", Parallel => "PARALLEL", Param => "PARAM", Passhash => "PASSHASH", diff --git a/lib/tests/define.rs b/lib/tests/define.rs index 9bd0cc62..9a844bbc 100644 --- a/lib/tests/define.rs +++ b/lib/tests/define.rs @@ -1981,6 +1981,7 @@ async fn define_remove_analyzer() -> Result<(), Error> { let sql = " DEFINE ANALYZER example_blank TOKENIZERS blank; DEFINE ANALYZER IF NOT EXISTS example_blank TOKENIZERS blank; + DEFINE ANALYZER OVERWRITE example_blank TOKENIZERS blank; DEFINE ANALYZER example_blank TOKENIZERS blank; REMOVE ANALYZER IF EXISTS example_blank; REMOVE ANALYZER example_blank; @@ -1989,6 +1990,7 @@ async fn define_remove_analyzer() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The analyzer 'example_blank' already exists")?; t.skip_ok(1)?; t.expect_error("The analyzer 'example_blank' does not exist")?; @@ -2001,6 +2003,7 @@ async fn define_remove_database() -> Result<(), Error> { let sql = " DEFINE DATABASE example; DEFINE DATABASE IF NOT EXISTS example; + DEFINE DATABASE OVERWRITE example; DEFINE DATABASE example; REMOVE DATABASE IF EXISTS example; REMOVE DATABASE example; @@ -2009,6 +2012,7 @@ async fn define_remove_database() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The database 'example' already exists")?; t.skip_ok(1)?; t.expect_error("The database 'example' does not exist")?; @@ -2021,6 +2025,7 @@ async fn define_remove_event() -> Result<(), Error> { let sql = " DEFINE EVENT example ON example THEN {}; DEFINE EVENT IF NOT EXISTS example ON example THEN {}; + DEFINE EVENT OVERWRITE example ON example THEN {}; DEFINE EVENT example ON example THEN {}; REMOVE EVENT IF EXISTS example ON example; REMOVE EVENT example ON example; @@ -2029,6 +2034,7 @@ async fn define_remove_event() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The event 'example' already exists")?; t.skip_ok(1)?; t.expect_error("The event 'example' does not exist")?; @@ -2041,6 +2047,7 @@ async fn define_remove_field() -> Result<(), Error> { let sql = " DEFINE FIELD example ON example; DEFINE FIELD IF NOT EXISTS example ON example; + DEFINE FIELD OVERWRITE example ON example; DEFINE FIELD example ON example; REMOVE FIELD IF EXISTS example ON example; REMOVE FIELD example ON example; @@ -2049,6 +2056,7 @@ async fn define_remove_field() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The field 'example' already exists")?; t.skip_ok(1)?; t.expect_error("The field 'example' does not exist")?; @@ -2061,6 +2069,7 @@ async fn define_remove_function() -> Result<(), Error> { let sql = " DEFINE FUNCTION fn::example() {}; DEFINE FUNCTION IF NOT EXISTS fn::example() {}; + DEFINE FUNCTION OVERWRITE fn::example() {}; DEFINE FUNCTION fn::example() {}; REMOVE FUNCTION IF EXISTS fn::example(); REMOVE FUNCTION fn::example(); @@ -2069,6 +2078,7 @@ async fn define_remove_function() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The function 'fn::example' already exists")?; t.skip_ok(1)?; t.expect_error("The function 'fn::example' does not exist")?; @@ -2081,6 +2091,7 @@ async fn define_remove_indexes() -> Result<(), Error> { let sql = " DEFINE INDEX example ON example FIELDS example; DEFINE INDEX IF NOT EXISTS example ON example FIELDS example; + DEFINE INDEX OVERWRITE example ON example FIELDS example; DEFINE INDEX example ON example FIELDS example; REMOVE INDEX IF EXISTS example ON example; REMOVE INDEX example ON example; @@ -2089,6 +2100,7 @@ async fn define_remove_indexes() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The index 'example' already exists")?; t.skip_ok(1)?; t.expect_error("The index 'example' does not exist")?; @@ -2101,6 +2113,7 @@ async fn define_remove_namespace() -> Result<(), Error> { let sql = " DEFINE NAMESPACE example; DEFINE NAMESPACE IF NOT EXISTS example; + DEFINE NAMESPACE OVERWRITE example; DEFINE NAMESPACE example; REMOVE NAMESPACE IF EXISTS example; REMOVE NAMESPACE example; @@ -2109,6 +2122,7 @@ async fn define_remove_namespace() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The namespace 'example' already exists")?; t.skip_ok(1)?; t.expect_error("The namespace 'example' does not exist")?; @@ -2121,6 +2135,7 @@ async fn define_remove_param() -> Result<(), Error> { let sql = " DEFINE PARAM $example VALUE 123; DEFINE PARAM IF NOT EXISTS $example VALUE 123; + DEFINE PARAM OVERWRITE $example VALUE 123; DEFINE PARAM $example VALUE 123; REMOVE PARAM IF EXISTS $example; REMOVE PARAM $example; @@ -2129,6 +2144,7 @@ async fn define_remove_param() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The param '$example' already exists")?; t.skip_ok(1)?; t.expect_error("The param '$example' does not exist")?; @@ -2141,6 +2157,7 @@ async fn define_remove_access() -> Result<(), Error> { let sql = " DEFINE ACCESS example ON DATABASE TYPE JWT ALGORITHM HS512 KEY 'secret'; DEFINE ACCESS IF NOT EXISTS example ON DATABASE TYPE JWT ALGORITHM HS512 KEY 'secret'; + DEFINE ACCESS OVERWRITE example ON DATABASE TYPE JWT ALGORITHM HS512 KEY 'secret'; DEFINE ACCESS example ON DATABASE TYPE JWT ALGORITHM HS512 KEY 'secret'; REMOVE ACCESS IF EXISTS example ON DB; REMOVE ACCESS example ON DB; @@ -2149,6 +2166,7 @@ async fn define_remove_access() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The access method 'example' already exists in the database 'test'")?; t.skip_ok(1)?; t.expect_error("The access method 'example' does not exist in the database 'test'")?; @@ -2161,6 +2179,7 @@ async fn define_remove_tables() -> Result<(), Error> { let sql = " DEFINE TABLE example; DEFINE TABLE IF NOT EXISTS example; + DEFINE TABLE OVERWRITE example; DEFINE TABLE example; REMOVE TABLE IF EXISTS example; REMOVE TABLE example; @@ -2169,6 +2188,7 @@ async fn define_remove_tables() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The table 'example' already exists")?; t.skip_ok(1)?; t.expect_error("The table 'example' does not exist")?; @@ -2181,6 +2201,7 @@ async fn define_remove_users() -> Result<(), Error> { let sql = " DEFINE USER example ON ROOT PASSWORD \"example\" ROLES OWNER DURATION FOR TOKEN 15m, FOR SESSION 6h; DEFINE USER IF NOT EXISTS example ON ROOT PASSWORD \"example\" ROLES OWNER DURATION FOR TOKEN 15m, FOR SESSION 6h; + DEFINE USER OVERWRITE example ON ROOT PASSWORD \"example\" ROLES OWNER DURATION FOR TOKEN 15m, FOR SESSION 6h; DEFINE USER example ON ROOT PASSWORD \"example\" ROLES OWNER DURATION FOR TOKEN 15m, FOR SESSION 6h; REMOVE USER IF EXISTS example ON ROOT; REMOVE USER example ON ROOT; @@ -2189,6 +2210,7 @@ async fn define_remove_users() -> Result<(), Error> { let mut t = Test::new(sql).await?; t.skip_ok(1)?; t.expect_val("None")?; + t.skip_ok(1)?; t.expect_error("The root user 'example' already exists")?; t.skip_ok(1)?; t.expect_error("The root user 'example' does not exist")?;