1pub mod comment;
4pub mod common;
5pub mod create_keyspace;
6pub mod delete;
7pub mod reserved;
8pub mod select;
9pub mod r#where;
10
11use comment::parse_comment;
12pub use common::{Column, Value, Variable};
13use create_keyspace::CreateKeyspaceQuery;
14pub use delete::DeleteQuery;
15pub use r#where::{ComparisonOperator, WhereClause};
16pub use select::SelectQuery;
17
18use nom::{branch::alt, combinator::map, error::Error, multi::many0, Err, IResult};
19
20#[derive(Debug, PartialEq)]
45pub enum Query {
46 Select(SelectQuery),
48 Delete(DeleteQuery),
50 CreateKeyspace(CreateKeyspaceQuery),
52}
53
54pub fn parse_query(input: &str) -> IResult<&str, Query> {
56 let input = input.trim();
58 let (input, _) = many0(parse_comment)(input)?;
60 let input = input.trim();
61 println!("input: {input:#?}");
62
63 alt((
64 map(select::parse_select, Query::Select),
65 map(delete::parse_delete, Query::Delete),
66 map(
67 create_keyspace::parse_create_keyspace,
68 Query::CreateKeyspace,
69 ),
70 ))(input)
71}
72
73impl<'a> TryFrom<&'a str> for Query {
74 type Error = Err<Error<&'a str>>;
75
76 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
77 Ok(parse_query(value)?.1)
78 }
79}
80
81pub fn parse_query_file(input: &str) -> IResult<&str, Vec<Query>> {
84 let trimmed = input.trim();
85
86 let (input, queries) = nom::multi::separated_list1(
87 nom::character::complete::multispace0,
88 nom::sequence::terminated(parse_query, nom::character::complete::multispace0),
89 )(trimmed)?;
90
91 Ok((input, queries))
92}
93
94#[cfg(test)]
95mod test {
96 use super::*;
97 use pretty_assertions::assert_eq;
98
99 #[test]
100 fn test_query_select() {
101 let query = "/* this is a comment */ select id, name, age
102 from person
103 where id = :id
104 and name = :name
105 and age > ?
106 limit 10";
107 println!("query: {:#?}", query);
108
109 let query = Query::try_from(query);
110
111 assert_eq!(
112 query,
113 Ok(Query::Select(SelectQuery {
114 table: "person".to_string(),
115 columns: vec![
116 Column::Identifier("id".to_string()),
117 Column::Identifier("name".to_string()),
118 Column::Identifier("age".to_string()),
119 ],
120 condition: vec![
121 WhereClause {
122 column: Column::Identifier("id".to_string()),
123 operator: ComparisonOperator::Equal,
124 value: Value::Variable(Variable::NamedVariable("id".to_string())),
125 },
126 WhereClause {
127 column: Column::Identifier("name".to_string()),
128 operator: ComparisonOperator::Equal,
129 value: Value::Variable(Variable::NamedVariable("name".to_string())),
130 },
131 WhereClause {
132 column: Column::Identifier("age".to_string()),
133 operator: ComparisonOperator::GreaterThan,
134 value: Value::Variable(Variable::Placeholder),
135 },
136 ],
137 limit: Some(Value::Number(10)),
138 }))
139 );
140 }
141}