From 595c994062e77a49b7ebc8977557987dd0a9fe88 Mon Sep 17 00:00:00 2001 From: Micha de Vries Date: Fri, 19 Jan 2024 12:35:52 +0000 Subject: [PATCH] Implement missing errors for missing clauses on `DEFINE`-statements (#3356) --- lib/src/syn/v1/stmt/define/event.rs | 23 +++++++++++++++++++++-- lib/src/syn/v1/stmt/define/index.rs | 20 ++++++++++++++++++-- lib/src/syn/v1/stmt/define/param.rs | 27 ++++++++++++++++++++++++--- lib/src/syn/v1/stmt/define/token.rs | 26 +++++++++++++++++++++++--- 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/lib/src/syn/v1/stmt/define/event.rs b/lib/src/syn/v1/stmt/define/event.rs index bed1a60e..408677f0 100644 --- a/lib/src/syn/v1/stmt/define/event.rs +++ b/lib/src/syn/v1/stmt/define/event.rs @@ -4,7 +4,7 @@ use super::super::super::{ error::{expect_tag_no_case, expected}, literal::{ident, strand}, value::{value, values}, - IResult, + IResult, ParseError, }; use crate::sql::{statements::DefineEventStatement, Strand, Value, Values}; use nom::{ @@ -13,6 +13,7 @@ use nom::{ combinator::{cut, opt}, multi::many0, sequence::tuple, + Err, }; pub fn event(i: &str) -> IResult<&str, DefineEventStatement> { @@ -52,7 +53,11 @@ pub fn event(i: &str) -> IResult<&str, DefineEventStatement> { } // Check necessary options if res.then.is_empty() { - // TODO throw error + return Err(Err::Failure(ParseError::ExplainedExpected { + tried: i, + expected: "a THEN clause", + explained: "An event requires a THEN clause to be defined.", + })); } // Return the statement Ok((i, res)) @@ -91,3 +96,17 @@ fn event_comment(i: &str) -> IResult<&str, DefineEventOption> { let (i, v) = cut(strand)(i)?; Ok((i, DefineEventOption::Comment(v))) } + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn define_event_without_then_clause() { + let sql = "EVENT test ON test"; + let res = event(sql); + + assert_eq!(res.is_err(), true) + } +} diff --git a/lib/src/syn/v1/stmt/define/index.rs b/lib/src/syn/v1/stmt/define/index.rs index 6bebb4dc..27bdfbcf 100644 --- a/lib/src/syn/v1/stmt/define/index.rs +++ b/lib/src/syn/v1/stmt/define/index.rs @@ -7,13 +7,17 @@ use super::super::super::{ part::index, IResult, }; -use crate::sql::{statements::DefineIndexStatement, Idioms, Index, Strand}; +use crate::{ + sql::{statements::DefineIndexStatement, Idioms, Index, Strand}, + syn::v1::ParseError, +}; use nom::{ branch::alt, bytes::complete::tag_no_case, combinator::{cut, opt}, multi::many0, sequence::tuple, + Err, }; pub fn index(i: &str) -> IResult<&str, DefineIndexStatement> { @@ -52,7 +56,11 @@ pub fn index(i: &str) -> IResult<&str, DefineIndexStatement> { } // Check necessary options if res.cols.is_empty() { - // TODO throw error + return Err(Err::Failure(ParseError::ExplainedExpected { + tried: i, + expected: "a COLUMNS or FIELDS clause", + explained: "An index requires a COLUMNS or FIELDS clause to be defined.", + })); } // Return the statement Ok((i, res)) @@ -231,4 +239,12 @@ mod tests { "DEFINE INDEX my_index ON my_table FIELDS my_col MTREE DIMENSION 4 DIST EUCLIDEAN TYPE F64 CAPACITY 40 DOC_IDS_ORDER 100 DOC_IDS_CACHE 100 MTREE_CACHE 100" ); } + + #[test] + fn define_index_without_columns_clause() { + let sql = "INDEX test ON test"; + let res = index(sql); + + assert_eq!(res.is_err(), true) + } } diff --git a/lib/src/syn/v1/stmt/define/param.rs b/lib/src/syn/v1/stmt/define/param.rs index 4217e7c4..03af2719 100644 --- a/lib/src/syn/v1/stmt/define/param.rs +++ b/lib/src/syn/v1/stmt/define/param.rs @@ -7,10 +7,13 @@ use super::super::super::{ value::value, IResult, }; -use crate::sql::{statements::DefineParamStatement, Permission, Strand, Value}; +use crate::{ + sql::{statements::DefineParamStatement, Permission, Strand, Value}, + syn::v1::ParseError, +}; use nom::{ branch::alt, bytes::complete::tag_no_case, character::complete::char, combinator::cut, - multi::many0, + multi::many0, Err, }; pub fn param(i: &str) -> IResult<&str, DefineParamStatement> { @@ -41,7 +44,11 @@ pub fn param(i: &str) -> IResult<&str, DefineParamStatement> { } // Check necessary options if res.value.is_none() { - // TODO throw error + return Err(Err::Failure(ParseError::ExplainedExpected { + tried: i, + expected: "a VALUE clause", + explained: "A param requires a VALUE clause to be defined.", + })); } // Return the statement Ok((i, res)) @@ -80,3 +87,17 @@ fn param_permissions(i: &str) -> IResult<&str, DefineParamOption> { let (i, v) = cut(permission)(i)?; Ok((i, DefineParamOption::Permissions(v))) } + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn define_param_without_value_clause() { + let sql = "PARAM test"; + let res = param(sql); + + assert_eq!(res.is_err(), true) + } +} diff --git a/lib/src/syn/v1/stmt/define/token.rs b/lib/src/syn/v1/stmt/define/token.rs index 3ae5c108..41e54084 100644 --- a/lib/src/syn/v1/stmt/define/token.rs +++ b/lib/src/syn/v1/stmt/define/token.rs @@ -8,8 +8,10 @@ use super::super::super::{ part::base_or_scope, IResult, }; -use crate::sql::{statements::DefineTokenStatement, Algorithm, Strand}; -#[cfg(not(feature = "jwks"))] +use crate::{ + sql::{statements::DefineTokenStatement, Algorithm, Strand}, + syn::v1::ParseError, +}; use nom::Err; use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0}; @@ -55,7 +57,11 @@ pub fn token(i: &str) -> IResult<&str, DefineTokenStatement> { } // Check necessary options if res.code.is_empty() { - // TODO throw error + return Err(Err::Failure(ParseError::ExplainedExpected { + tried: i, + expected: "a VALUE clause", + explained: "A token requires a VALUE clause to be defined.", + })); } // Return the statement Ok((i, res)) @@ -94,3 +100,17 @@ fn token_comment(i: &str) -> IResult<&str, DefineTokenOption> { let (i, v) = cut(strand)(i)?; Ok((i, DefineTokenOption::Comment(v))) } + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn define_token_without_value_clause() { + let sql = "TOKEN test ON test"; + let res = token(sql); + + assert_eq!(res.is_err(), true) + } +}