Skip to content

Commit

Permalink
wip: add test for query command
Browse files Browse the repository at this point in the history
  • Loading branch information
StoneDot committed Mar 24, 2024
1 parent 35db588 commit 823ec1d
Show file tree
Hide file tree
Showing 4 changed files with 364 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ pub struct Context {
pub overwritten_table_name: Option<String>, // --table option
pub overwritten_port: Option<u32>, // --port option
pub output: Option<String>,
should_strict_for_query: Option<bool>,
pub should_strict_for_query: Option<bool>,
}

/*
Expand Down
3 changes: 3 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ async fn dispatch(context: &mut app::Context, subcommand: cmd::Sub) -> Result<()
return Err("Cannot specify both --strict and --non-strict".into());
}
context.output = output;
if strict || non_strict {
context.should_strict_for_query = Some(strict || !non_strict)
}
data::query(
context.clone(),
QueryParams {
Expand Down
87 changes: 71 additions & 16 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,12 +334,29 @@ impl Display for InvalidTypesError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Invalid type detected. Expected type is {}, but actual type is {}",
"Invalid type detected. Expected type is {}, but actual type is {}.",
self.expected_type, self.actual_type
)
}
}

/// The error context of invalid type
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct InvalidTypesWithSuggestError {
pub expected_type: AttributeType,
pub actual_type: AttributeType,
pub suggest: String,
}

impl Display for InvalidTypesWithSuggestError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Invalid type detected. Expected type is {}, but actual type is {}.\nDid you intend '{}'?",
self.expected_type, self.actual_type, self.suggest
)
}
}
/// The error context of a parsing error
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub enum ParseError {
Expand All @@ -351,6 +368,7 @@ pub enum ParseError {
InvalidEscapeByte(EscapeByteError),
InvalidBeingsWith(String),
InvalidTypes(InvalidTypesError),
InvalidTypesWithSuggest(InvalidTypesWithSuggestError),
}

impl Display for ParseError {
Expand Down Expand Up @@ -380,6 +398,9 @@ impl Display for ParseError {
ParseError::InvalidTypes(err) => {
write!(f, "{}", err)
}
ParseError::InvalidTypesWithSuggest(err) => {
write!(f, "{}", err)
}
}
}
}
Expand All @@ -399,8 +420,8 @@ enum AttrVal {
}

impl AttrVal {
fn is_type(&self, t: &AttributeType) -> bool {
self.attribute_type() == *t
fn is_type(&self, t: AttributeType) -> bool {
self.attribute_type() == t
}

fn attribute_type(&self) -> AttributeType {
Expand Down Expand Up @@ -1400,7 +1421,7 @@ impl DyneinParser {
}
})?;
let condition = parse_sort_key_condition(pair.next().unwrap())?;
self.process_sort_key(sort_attr, condition)
self.process_sort_key(exp, sort_attr, condition)
}

/// Parse sort key condition in strict mode.
Expand All @@ -1412,7 +1433,7 @@ impl DyneinParser {
let mut pair = GeneratedParser::parse(Rule::sort_key, exp)
.map_err(|err| ParseError::ParsingError(Box::new(err)))?;
let condition = parse_sort_key_condition(pair.next().unwrap())?;
self.process_sort_key(sort_attr, condition)
self.process_sort_key(exp, sort_attr, condition)
}

pub fn parse_put_content(
Expand Down Expand Up @@ -1489,7 +1510,7 @@ impl DyneinParser {
sort_attr: &AttributeDefinition,
) -> Result<ExpressionResult, ParseError> {
let condition = self.try_parse_sort_key_for_string(exp)?;
self.process_sort_key(sort_attr, condition)
self.process_sort_key(exp, sort_attr, condition)
}

fn try_parse_sort_key_for_number(&self, exp: &str) -> Result<SortKeyCondition, ParseError> {
Expand All @@ -1506,7 +1527,7 @@ impl DyneinParser {
sort_attr: &AttributeDefinition,
) -> Result<ExpressionResult, ParseError> {
let condition = self.try_parse_sort_key_for_number(exp)?;
self.process_sort_key(sort_attr, condition)
self.process_sort_key(exp, sort_attr, condition)
}

fn get_or_create_attr_name_ref(&mut self, attr_name: String) -> String {
Expand Down Expand Up @@ -1623,18 +1644,30 @@ impl DyneinParser {

fn process_sort_key(
&mut self,
exp: &str,
sort_attr: &AttributeDefinition,
condition: SortKeyCondition,
) -> Result<ExpressionResult, ParseError> {
let mut expression = String::new();
let attr_type = &sort_attr.attribute_type;
let attr_type = sort_attr.attribute_type;
let attr_name = &sort_attr.attribute_name;
let mut process_op = |val: AttrVal, op: &str| -> Result<ExpressionResult, ParseError> {
if !val.is_type(attr_type) {
Err(ParseError::InvalidTypes(InvalidTypesError {
expected_type: attr_type.to_owned(),
actual_type: val.attribute_type(),
}))?;
let fallback_result = self.try_sort_key_parse(exp, sort_attr);
let err = match fallback_result {
Some(exp) => {
ParseError::InvalidTypesWithSuggest(InvalidTypesWithSuggestError {
expected_type: attr_type.to_owned(),
actual_type: val.attribute_type(),
suggest: format!("{}", exp),
})
}
None => ParseError::InvalidTypes(InvalidTypesError {
expected_type: attr_type.to_owned(),
actual_type: val.attribute_type(),
}),
};
Err(err)?;
}
let path = self.get_or_create_attr_name_ref(attr_name.to_owned());
let value = self.process_literal(val)?;
Expand Down Expand Up @@ -1682,6 +1715,12 @@ impl DyneinParser {
})
}
SortKeyCondition::BeginsWith(prefix) => {
if !prefix.is_type(attr_type) {
Err(ParseError::InvalidTypes(InvalidTypesError {
expected_type: attr_type.to_owned(),
actual_type: prefix.attribute_type(),
}))?;
}
let path = self.get_or_create_attr_name_ref(attr_name.to_owned());
let prefix = self.process_literal(prefix)?;
expression.push_str("begins_with(");
Expand Down Expand Up @@ -2607,13 +2646,29 @@ mod tests {
op_in[i],
&AttributeDefinition::new("id", AttributeType::S),
),
Err(ParseError::InvalidTypes(InvalidTypesError {
expected_type: AttributeType::S,
actual_type: AttributeType::N,
}))
Err(ParseError::InvalidTypesWithSuggest(
InvalidTypesWithSuggestError {
expected_type: AttributeType::S,
actual_type: AttributeType::N,
suggest: format!("{} \"{}\"", expected_op[i], expected_val[i]),
}
))
);
}

// test invalid type input
parser.clear();
assert_eq!(
parser.parse_sort_key_without_fallback(
r#"= "1*3""#,
&AttributeDefinition::new("id", AttributeType::N),
),
Err(ParseError::InvalidTypes(InvalidTypesError {
expected_type: AttributeType::N,
actual_type: AttributeType::S,
}))
);

// test between in non-strict for string types
parser.clear();
assert_eq!(
Expand Down
Loading

0 comments on commit 823ec1d

Please sign in to comment.