Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump nom to v5 #53

Merged
merged 44 commits into from
Feb 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
bfa5462
Bump nom to v5.0.1
tomharmon Dec 7, 2019
c226dbe
Partial updates to `common.rs`
tomharmon Dec 7, 2019
72bb1dd
Add TODO for last compile error in `common.rs`
tomharmon Dec 8, 2019
d2b8b77
Update `compond_select.rs`
tomharmon Dec 8, 2019
29bee21
Fixed compile time errors in insert.rs
SamedhG Dec 8, 2019
9869b49
Fixed compile time errors in keyword, order and select
SamedhG Dec 8, 2019
99519e3
Update `condition.rs`
tomharmon Dec 8, 2019
5808b44
Fixed compile time errors in set and update
SamedhG Dec 8, 2019
170533d
Update `create.rs` and `create_table_options.rs`
tomharmon Dec 8, 2019
a820898
Fixed compile time errors in parser and common
SamedhG Dec 8, 2019
5cdeeaa
Fixed compile time errors in more files
SamedhG Dec 8, 2019
bfacbd6
Replace `opt_multispace` with `multispace0`
tomharmon Dec 11, 2019
106fa01
Replace `set.rs` macros w functions, fix compile
tomharmon Dec 31, 2019
b293a3f
Rewrite `update.rs` to use nom v5 functions
tomharmon Dec 31, 2019
d5dec81
Update `parser.rs` to use nom v5 functions
tomharmon Jan 1, 2020
8a667dd
Update `select.rs` to use nom v5 functions
tomharmon Jan 1, 2020
1d29161
Update `order.rs` to use nom v5 functions
tomharmon Jan 1, 2020
32a7d1b
Update `join.rs` to use nom v5 functions
tomharmon Jan 1, 2020
045f514
Update `insert.rs` to use nom v5 functions
tomharmon Jan 1, 2020
86ac840
Update delete and drop to use nom v5 functions
tomharmon Jan 1, 2020
a4cbae3
Use nom v5 functions for create
tomharmon Jan 2, 2020
dafae2b
Update `condition.rs` to use nom v5 functions
tomharmon Jan 2, 2020
4c831bf
Update case, compound_select to nom v5
tomharmon Jan 2, 2020
bde5ce5
Use shorthand for constructor args
tomharmon Jan 2, 2020
823a971
Formatting
tomharmon Jan 2, 2020
03dbbcf
Update `arithmetic.rs` to use nom v5 functions
tomharmon Jan 2, 2020
9b68403
Partial work on updating `common` to nom v5
tomharmon Jan 2, 2020
a6557f4
Update `statement_terminator` to nom v5
tomharmon Jan 2, 2020
8079641
Partial update to `common` to nom v5
tomharmon Jan 2, 2020
5f32f9c
More work on upgrading common to nom v5
tomharmon Jan 3, 2020
3d31bb1
Use ws_sep_comma from common within crate
tomharmon Jan 3, 2020
2824f1e
Make `raw_string_[single/double]_quote` snake case
tomharmon Jan 3, 2020
2cbebcf
Finish upgrading common to nom v5
tomharmon Jan 3, 2020
da68068
Format + fix common tests
tomharmon Jan 3, 2020
2677555
Add TODO for selecting literals
tomharmon Jan 4, 2020
b287e5f
Convert keywords to complete nom v5 functions
tomharmon Jan 4, 2020
7789a2f
Fix insert unit test
tomharmon Jan 4, 2020
5b78728
Fix minor bugs
tomharmon Jan 7, 2020
bef5b7a
Remove unnecessary level of bracing
spazm Feb 3, 2020
1b38260
Require trailing spaces after "natural" in join clause
spazm Feb 3, 2020
c63a33b
extract repeated code from create_option parsing.
spazm Feb 3, 2020
ec3b281
Merge pull request #5 from spazm/upgrade-nom
tomharmon Feb 3, 2020
40b1072
add back TODO comment for table options
tomharmon Feb 3, 2020
9fafd10
Add comment explaining max tuple size for alt
tomharmon Feb 3, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ license = "MIT"
[dependencies]
serde = "1.0"
serde_derive = "1.0"
nom = "^4.2.0"
nom = "5.0.1"

[dev-dependencies]
pretty_assertions = "0.5.1"
139 changes: 74 additions & 65 deletions src/arithmetic.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use nom::multispace;
use nom::types::CompleteByteSlice;
use nom::character::complete::{multispace0, multispace1};
use std::{fmt, str};

use column::Column;
use common::{
as_alias, column_identifier_no_alias, integer_literal, opt_multispace, type_identifier,
Literal, SqlType,
as_alias, column_identifier_no_alias, integer_literal, type_identifier, Literal, SqlType,
};
use nom::branch::alt;
use nom::bytes::complete::{tag, tag_no_case};
use nom::combinator::{map, opt};
use nom::sequence::{terminated, tuple};
use nom::IResult;

#[derive(Debug, Clone, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum ArithmeticOperator {
Expand Down Expand Up @@ -38,10 +41,10 @@ impl ArithmeticExpression {
alias: Option<String>,
) -> Self {
Self {
op: op,
left: left,
right: right,
alias: alias,
op,
left,
right,
alias,
}
}
}
Expand Down Expand Up @@ -75,69 +78,76 @@ impl fmt::Display for ArithmeticExpression {
}
}

named!(pub arithmetic_cast<CompleteByteSlice, (ArithmeticBase, Option<SqlType>)>,
alt!(
do_parse!(
tag_no_case!("cast") >>
opt_multispace >>
tag!("(") >>
opt_multispace >>
// TODO(malte): should be arbitrary expr
v: arithmetic_base >>
multispace >>
tag_no_case!("as") >>
multispace >>
_sign: opt!(terminated!(tag_no_case!("signed"), multispace)) >>
typ: type_identifier >>
opt_multispace >>
tag!(")") >>
(v, Some(typ))
) |
map!(arithmetic_base, |v| (v, None))
)
);
fn arithmetic_cast_helper(i: &[u8]) -> IResult<&[u8], (ArithmeticBase, Option<SqlType>)> {
let (remaining_input, (_, _, _, _, a_base, _, _, _, _sign, sql_type, _, _)) = tuple((
tag_no_case("cast"),
multispace0,
tag("("),
multispace0,
// TODO(malte): should be arbitrary expr
arithmetic_base,
multispace1,
tag_no_case("as"),
multispace1,
opt(terminated(tag_no_case("signed"), multispace1)),
type_identifier,
multispace0,
tag(")"),
))(i)?;

Ok((remaining_input, (a_base, Some(sql_type))))
}

pub fn arithmetic_cast(i: &[u8]) -> IResult<&[u8], (ArithmeticBase, Option<SqlType>)> {
alt((arithmetic_cast_helper, map(arithmetic_base, |v| (v, None))))(i)
}

// Parse standard math operators.
// TODO(malte): this doesn't currently observe operator precedence.
named!(pub arithmetic_operator<CompleteByteSlice, ArithmeticOperator>,
alt!(
map!(tag!("+"), |_| ArithmeticOperator::Add)
| map!(tag!("-"), |_| ArithmeticOperator::Subtract)
| map!(tag!("*"), |_| ArithmeticOperator::Multiply)
| map!(tag!("/"), |_| ArithmeticOperator::Divide)
)
);
pub fn arithmetic_operator(i: &[u8]) -> IResult<&[u8], ArithmeticOperator> {
alt((
map(tag("+"), |_| ArithmeticOperator::Add),
map(tag("-"), |_| ArithmeticOperator::Subtract),
map(tag("*"), |_| ArithmeticOperator::Multiply),
map(tag("/"), |_| ArithmeticOperator::Divide),
))(i)
}

// Base case for nested arithmetic expressions: column name or literal.
named!(pub arithmetic_base<CompleteByteSlice, ArithmeticBase>,
alt!(
map!(integer_literal, |il| ArithmeticBase::Scalar(il))
| map!(column_identifier_no_alias, |ci| ArithmeticBase::Column(ci))
)
);
pub fn arithmetic_base(i: &[u8]) -> IResult<&[u8], ArithmeticBase> {
alt((
map(integer_literal, |il| ArithmeticBase::Scalar(il)),
map(column_identifier_no_alias, |ci| ArithmeticBase::Column(ci)),
))(i)
}

// Parse simple arithmetic expressions combining literals, and columns and literals.
// TODO(malte): this doesn't currently support nested expressions.
named!(pub arithmetic_expression<CompleteByteSlice, ArithmeticExpression>,
do_parse!(
left: arithmetic_cast >>
opt_multispace >>
op: arithmetic_operator >>
opt_multispace >>
right: arithmetic_cast >>
alias: opt!(as_alias) >>
(ArithmeticExpression {
op: op,
// TODO(malte): discards casts
pub fn arithmetic_expression(i: &[u8]) -> IResult<&[u8], ArithmeticExpression> {
let (remaining_input, (left, _, op, _, right, opt_alias)) = tuple((
arithmetic_cast,
multispace0,
arithmetic_operator,
multispace0,
arithmetic_cast,
opt(as_alias),
))(i)?;

let alias = match opt_alias {
None => None,
Some(a) => Some(String::from(a)),
};

Ok((
remaining_input,
ArithmeticExpression {
left: left.0,
right: right.0,
alias: match alias {
None => None,
Some(a) => Some(String::from(a)),
},
})
)
);
op,
alias,
},
))
}

#[cfg(test)]
mod tests {
Expand Down Expand Up @@ -209,13 +219,13 @@ mod tests {
];

for (i, e) in lit_ae.iter().enumerate() {
let res = arithmetic_expression(CompleteByteSlice(e.as_bytes()));
let res = arithmetic_expression(e.as_bytes());
assert!(res.is_ok());
assert_eq!(res.unwrap().1, expected_lit_ae[i]);
}

for (i, e) in col_lit_ae.iter().enumerate() {
let res = arithmetic_expression(CompleteByteSlice(e.as_bytes()));
let res = arithmetic_expression(e.as_bytes());
assert!(res.is_ok());
assert_eq!(res.unwrap().1, expected_col_lit_ae[i]);
}
Expand Down Expand Up @@ -281,10 +291,9 @@ mod tests {
];

for (i, e) in exprs.iter().enumerate() {
let res = arithmetic_expression(CompleteByteSlice(e.as_bytes()));
let res = arithmetic_expression(e.as_bytes());
assert!(res.is_ok(), "{} failed to parse", e);
assert_eq!(res.unwrap().1, expected[i]);
}
}

}
64 changes: 37 additions & 27 deletions src/case.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use nom::types::CompleteByteSlice;
use std::fmt;

use column::Column;
use common::{column_identifier_no_alias, literal, opt_multispace, Literal};
use common::{column_identifier_no_alias, literal, Literal};
use condition::{condition_expr, ConditionExpression};

use nom::bytes::complete::tag_no_case;
use nom::character::complete::multispace0;
use nom::combinator::opt;
use nom::sequence::{delimited, terminated, tuple};
use nom::IResult;

#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum ColumnOrLiteral {
Column(Column),
Expand Down Expand Up @@ -38,28 +43,33 @@ impl fmt::Display for CaseWhenExpression {
}
}

named!(pub case_when_column<CompleteByteSlice, CaseWhenExpression>,
do_parse!(
tag_no_case!("case when") >>
opt_multispace >>
cond: condition_expr >>
opt_multispace >>
tag_no_case!("then") >>
opt_multispace >>
column: column_identifier_no_alias >>
opt_multispace >>
else_value: opt!(do_parse!(
tag_no_case!("else") >>
opt_multispace >>
else_val: literal >>
opt_multispace >>
(else_val)
)) >>
tag_no_case!("end") >>
(CaseWhenExpression {
condition: cond,
then_expr: ColumnOrLiteral::Column(column),
else_expr: else_value.map(|v| ColumnOrLiteral::Literal(v)),
})
)
);
pub fn case_when_column(i: &[u8]) -> IResult<&[u8], CaseWhenExpression> {
let (remaining_input, (_, _, condition, _, _, _, column, _, else_val, _)) = tuple((
tag_no_case("case when"),
multispace0,
condition_expr,
multispace0,
tag_no_case("then"),
multispace0,
column_identifier_no_alias,
multispace0,
opt(delimited(
terminated(tag_no_case("else"), multispace0),
literal,
multispace0,
)),
tag_no_case("end"),
))(i)?;

let then_expr = ColumnOrLiteral::Column(column);
let else_expr = else_val.map(|v| ColumnOrLiteral::Literal(v));

Ok((
remaining_input,
CaseWhenExpression {
condition,
then_expr,
else_expr,
},
))
}
19 changes: 9 additions & 10 deletions src/column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,24 +185,24 @@ impl fmt::Display for ColumnSpecification {
}

impl ColumnSpecification {
pub fn new(c: Column, t: SqlType) -> ColumnSpecification {
pub fn new(column: Column, sql_type: SqlType) -> ColumnSpecification {
ColumnSpecification {
column: c,
sql_type: t,
column,
sql_type,
constraints: vec![],
comment: None,
}
}

pub fn with_constraints(
c: Column,
t: SqlType,
ccs: Vec<ColumnConstraint>,
column: Column,
sql_type: SqlType,
constraints: Vec<ColumnConstraint>,
) -> ColumnSpecification {
ColumnSpecification {
column: c,
sql_type: t,
constraints: ccs,
column,
sql_type,
constraints,
comment: None,
}
}
Expand Down Expand Up @@ -256,5 +256,4 @@ mod tests {
assert_eq!(format!("{}", c2), "count(*)");
assert_eq!(format!("{}", c3), "sum(mytab.foo)");
}

}
Loading