Skip to content

Commit

Permalink
Support from for parse before and after as (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
rcoh committed Jun 13, 2020
1 parent c889a20 commit 7b356ef
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 10 deletions.
49 changes: 39 additions & 10 deletions src/lang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ pub enum InlineOperator {
Parse {
pattern: Keyword,
fields: Vec<String>,
input_column: Option<Expr>,
input_column: (Option<Positioned<Expr>>, Option<Positioned<Expr>>),
no_drop: bool,
},
Fields {
Expand Down Expand Up @@ -547,14 +547,15 @@ named!(did_you_mean_aggregate<Span, Span>,
named!(parse<Span, Positioned<InlineOperator>>, with_pos!(ws!(do_parse!(
tag!("parse") >>
pattern: quoted_string >>
from_column_opt: opt!(ws!(preceded!(tag!("from"), expr))) >>
from_column_opt: opt!(with_pos!(ws!(preceded!(tag!("from"), expr)))) >>
tag!("as") >>
vars: var_list >>
from_column_opt_2: opt!(with_pos!(ws!(preceded!(tag!("from"), expr)))) >>
no_drop_opt: opt!(ws!(tag!("nodrop"))) >>
( InlineOperator::Parse{
pattern: Keyword::new_wildcard(pattern.to_string()),
fields: vars,
input_column: from_column_opt,
input_column: (from_column_opt, from_column_opt_2),
no_drop: no_drop_opt.is_some()
} )
))));
Expand Down Expand Up @@ -1001,7 +1002,7 @@ mod tests {
value: InlineOperator::Parse {
pattern: Keyword::new_wildcard("[key=*]".to_string()),
fields: vec!["v".to_string()],
input_column: None,
input_column: (None, None),
no_drop: false
}
}
Expand All @@ -1015,7 +1016,7 @@ mod tests {
value: InlineOperator::Parse {
pattern: Keyword::new_wildcard("[key=*]".to_string()),
fields: vec!["v".to_string()],
input_column: None,
input_column: (None, None),
no_drop: true
}
}
Expand All @@ -1029,7 +1030,7 @@ mod tests {
value: InlineOperator::Parse {
pattern: Keyword::new_wildcard("[key=*][val=*]".to_string()),
fields: vec!["k".to_string(), "v".to_string()],
input_column: None,
input_column: (None, None),
no_drop: true
}
}
Expand Down Expand Up @@ -1058,14 +1059,42 @@ mod tests {
);
expect!(
operator,
r#" parse "[key=*]" from field as v "#,
r#" parse "[key=*]" from field as v"#,
Operator::Inline(Positioned {
start_pos: QueryPosition(1),
end_pos: QueryPosition(32),
value: InlineOperator::Parse {
pattern: Keyword::new_wildcard("[key=*]".to_string()),
fields: vec!["v".to_string()],
input_column: (
Some(Positioned {
start_pos: QueryPosition(17),
end_pos: QueryPosition(28),
value: Expr::column("field")
}),
None
),
no_drop: false
},
})
);
expect!(
operator,
r#" parse "[key=*]" as v from field"#,
Operator::Inline(Positioned {
start_pos: QueryPosition(1),
end_pos: QueryPosition(33),
end_pos: QueryPosition(32),
value: InlineOperator::Parse {
pattern: Keyword::new_wildcard("[key=*]".to_string()),
fields: vec!["v".to_string()],
input_column: Some(Expr::column("field")),
input_column: (
None,
Some(Positioned {
start_pos: QueryPosition(22),
end_pos: QueryPosition(32),
value: Expr::column("field")
})
),
no_drop: false
},
})
Expand Down Expand Up @@ -1304,7 +1333,7 @@ mod tests {
value: InlineOperator::Parse {
pattern: Keyword::new_wildcard("!123*".to_string()),
fields: vec!["foo".to_string()],
input_column: None,
input_column: (None, None),
no_drop: false
}
}),
Expand Down
18 changes: 18 additions & 0 deletions src/typecheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ pub enum TypeError {
)]
ParseNumPatterns { pattern: usize, extracted: usize },

#[fail(display = "Two `from` clauses were provided")]
DoubleFromClause,

#[fail(display = "Limit must be a non-zero integer, found {}", limit)]
InvalidLimit { limit: f64 },
}
Expand Down Expand Up @@ -114,6 +117,21 @@ impl TypeCheck<Box<dyn operator::OperatorBuilder + Send + Sync>>
} => {
let regex = pattern.to_regex();

let input_column = match input_column {
(Some(from), None) | (None, Some(from)) => Some(from.value),
(None, None) => None,
(Some(l), Some(r)) => {
let e = TypeError::DoubleFromClause;
error_builder
.report_error_for(&e)
.with_code_pointer(&l, "")
.with_code_pointer(&r, "")
.with_resolution("Only one from clause is allowed")
.send_report();
return Err(e);
}
};

if (regex.captures_len() - 1) != fields.len() {
Err(TypeError::ParseNumPatterns {
pattern: regex.captures_len() - 1,
Expand Down
9 changes: 9 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ mod integration {
impl ErrorReporter for EmptyErrorReporter {}

#[test_resources("tests/structured_tests/*.toml")]
fn integration(path: &str) {
structured_test(path)
}

#[test_resources("tests/structured_tests/aliases/*.toml")]
fn alias(path: &str) {
structured_test(path)
}

fn structured_test(path: &str) {
let contents = fs::read_to_string(path).unwrap();
let conf: TestDefinition = toml::from_str(&contents).unwrap();
Expand Down
17 changes: 17 additions & 0 deletions tests/structured_tests/parse_error_double_from.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
query = "* | json | parse \"a * b\" from col as x from col"
input = """
{"level": "info", "message": "A thing happened", "num_things": 1102}
{"level": "error", "message": "Oh now an error!"}
"""
output = ""
error = """
error: Two `from` clauses were provided
|
1 | * | json | parse "a * b" from col as x from col
| ^^^^^^^^^
| ^^^^^^^^
|
= help: Only one from clause is allowed
Error: Two `from` clauses were provided
"""
succeeds = false

0 comments on commit 7b356ef

Please sign in to comment.