1use crate::ast::values::IntervalUnit;
2use crate::ast::*;
3use nom::{
4 IResult, Parser,
5 branch::alt,
6 bytes::complete::{tag, tag_no_case, take_while1},
7 character::complete::{char, digit1, multispace1},
8 combinator::{map, opt, recognize, value},
9 sequence::{delimited, preceded},
10};
11
12pub fn parse_identifier(input: &str) -> IResult<&str, &str> {
14 take_while1(|c: char| c.is_alphanumeric() || c == '_' || c == '.').parse(input)
15}
16
17pub fn parse_interval(input: &str) -> IResult<&str, Value> {
19 let (input, num_str) = digit1(input)?;
20 let amount: i64 = num_str.parse().unwrap_or(0);
21
22 let (input, unit) = alt((
23 value(IntervalUnit::Second, tag_no_case("s")),
24 value(IntervalUnit::Minute, tag_no_case("m")),
25 value(IntervalUnit::Hour, tag_no_case("h")),
26 value(IntervalUnit::Day, tag_no_case("d")),
27 value(IntervalUnit::Week, tag_no_case("w")),
28 value(IntervalUnit::Month, tag_no_case("mo")),
29 value(IntervalUnit::Year, tag_no_case("y")),
30 ))
31 .parse(input)?;
32
33 Ok((input, Value::Interval { amount, unit }))
34}
35
36pub fn parse_value(input: &str) -> IResult<&str, Value> {
38 alt((
39 map(preceded(char('$'), digit1), |d: &str| {
41 Value::Param(d.parse().unwrap_or(0))
42 }),
43 map(
45 preceded(
46 char(':'),
47 take_while1(|c: char| c.is_alphanumeric() || c == '_'),
48 ),
49 |name: &str| Value::NamedParam(name.to_string()),
50 ),
51 value(Value::Bool(true), tag_no_case("true")),
53 value(Value::Bool(false), tag_no_case("false")),
54 value(Value::Null, tag_no_case("null")),
56 map(
58 delimited(
59 char('"'),
60 nom::bytes::complete::take_while(|c| c != '"'),
61 char('"'),
62 ),
63 |s: &str| Value::String(s.to_string()),
64 ),
65 map(
67 delimited(
68 char('\''),
69 nom::bytes::complete::take_while(|c| c != '\''),
70 char('\''),
71 ),
72 |s: &str| Value::String(s.to_string()),
73 ),
74 map(
76 recognize((opt(char('-')), digit1, char('.'), digit1)),
77 |s: &str| Value::Float(s.parse().unwrap_or(0.0)),
78 ),
79 parse_interval,
81 map(recognize((opt(char('-')), digit1)), |s: &str| {
83 Value::Int(s.parse().unwrap_or(0))
84 }),
85 ))
86 .parse(input)
87}
88
89pub fn parse_operator(input: &str) -> IResult<&str, Operator> {
91 alt((
92 value(Operator::NotBetween, tag_no_case("not between")),
94 value(Operator::Between, tag_no_case("between")),
95 value(Operator::IsNotNull, tag_no_case("is not null")),
96 value(Operator::IsNull, tag_no_case("is null")),
97 value(Operator::NotIn, tag_no_case("not in")),
98 value(Operator::NotILike, tag_no_case("not ilike")),
99 value(Operator::NotLike, tag_no_case("not like")),
100 value(Operator::ILike, tag_no_case("ilike")),
101 value(Operator::Like, tag_no_case("like")),
102 value(Operator::In, tag_no_case("in")),
103 value(Operator::Gte, tag(">=")),
104 value(Operator::Lte, tag("<=")),
105 value(Operator::Ne, tag("!=")),
106 value(Operator::Ne, tag("<>")),
107 value(Operator::Eq, tag("=")),
109 value(Operator::Gt, tag(">")),
110 value(Operator::Lt, tag("<")),
111 value(Operator::Fuzzy, tag("~")),
112 ))
113 .parse(input)
114}
115
116pub fn parse_action(input: &str) -> IResult<&str, (Action, bool)> {
118 alt((
119 map(
121 (tag_no_case("get"), multispace1, tag_no_case("distinct")),
122 |_| (Action::Get, true),
123 ),
124 value((Action::Get, false), tag_no_case("get")),
126 value((Action::Set, false), tag_no_case("set")),
128 alt((
130 value((Action::Del, false), tag_no_case("delete")),
131 value((Action::Del, false), tag_no_case("del")),
132 )),
133 alt((
135 value((Action::Add, false), tag_no_case("insert")),
136 value((Action::Add, false), tag_no_case("add")),
137 )),
138 alt((
140 value((Action::Make, false), tag_no_case("create")),
141 value((Action::Make, false), tag_no_case("make")),
142 )),
143 ))
144 .parse(input)
145}
146
147pub fn parse_txn_command(input: &str) -> IResult<&str, Qail> {
149 let (input, action) = alt((
150 value(Action::TxnStart, tag_no_case("begin")),
151 value(Action::TxnCommit, tag_no_case("commit")),
152 value(Action::TxnRollback, tag_no_case("rollback")),
153 ))
154 .parse(input)?;
155
156 Ok((
157 input,
158 Qail {
159 action,
160 table: String::new(),
161 columns: vec![],
162 joins: vec![],
163 cages: vec![],
164 distinct: false,
165 distinct_on: vec![],
166 index_def: None,
167 table_constraints: vec![],
168 set_ops: vec![],
169 having: vec![],
170 group_by_mode: GroupByMode::default(),
171 ctes: vec![],
172 returning: None,
173 on_conflict: None,
174 source_query: None,
175 channel: None,
176 payload: None,
177 savepoint_name: None,
178 from_tables: vec![],
179 using_tables: vec![],
180 lock_mode: None,
181 fetch: None,
182 default_values: false,
183 overriding: None,
184 sample: None,
185 only_table: false,
186 },
187 ))
188}