1use crate::ast::span::Spanned;
2use crate::ast::{
3 Assignment, Delete, Insert, LITERAL_TABLE, OrderByExpr, Select, SelectItem, TableRef, Update,
4};
5use crate::error::{ParserError, Result};
6use crate::tokenizer::keyword::Keyword;
7use crate::tokenizer::token::{Token, Word};
8
9use super::Parser;
10
11impl<'a> Parser<'a> {
12 pub fn parse_select(&mut self) -> Result<Select> {
13 let start_span = self.expect_keyword("SELECT", Keyword::SELECT)?;
14 let distinct = self.consume_keyword(Keyword::DISTINCT);
15
16 let projection = self.parse_projection_list()?;
17 let mut end_span = projection
18 .last()
19 .map(|item| item.span())
20 .unwrap_or(start_span);
21
22 let from = if self.consume_keyword(Keyword::FROM) {
23 let from = self.parse_table_ref()?;
24 end_span = from.span;
25 from
26 } else {
27 validate_literal_projection(&projection)?;
28 TableRef {
29 name: LITERAL_TABLE.to_string(),
30 alias: None,
31 span: end_span,
32 }
33 };
34
35 let selection = if self.consume_keyword(Keyword::WHERE) {
36 let expr = self.parse_expr()?;
37 end_span = end_span.union(&expr.span());
38 Some(expr)
39 } else {
40 None
41 };
42
43 let order_by = if self.consume_keyword(Keyword::ORDER) {
44 self.expect_keyword("BY", Keyword::BY)?;
45 let items = self.parse_order_by()?;
46 if let Some(last) = items.last() {
47 end_span = end_span.union(&last.span);
48 }
49 items
50 } else {
51 Vec::new()
52 };
53
54 let mut limit = None;
55 let mut offset = None;
56 if self.consume_keyword(Keyword::LIMIT) {
57 let lim = self.parse_expr()?;
58 end_span = end_span.union(&lim.span());
59 limit = Some(lim);
60
61 if self.consume_keyword(Keyword::OFFSET) {
62 let off = self.parse_expr()?;
63 end_span = end_span.union(&off.span());
64 offset = Some(off);
65 }
66 }
67
68 let span = start_span.union(&end_span);
69 Ok(Select {
70 distinct,
71 projection,
72 from,
73 selection,
74 order_by,
75 limit,
76 offset,
77 span,
78 })
79 }
80
81 fn parse_projection_list(&mut self) -> Result<Vec<SelectItem>> {
82 let mut items = Vec::new();
83 loop {
84 items.push(self.parse_select_item()?);
85 if matches!(self.peek().token, Token::Comma) {
86 self.advance();
87 continue;
88 }
89 break;
90 }
91 Ok(items)
92 }
93
94 fn parse_select_item(&mut self) -> Result<SelectItem> {
95 let tok = self.peek().clone();
96 if matches!(tok.token, Token::Mul) {
97 self.advance();
98 return Ok(SelectItem::Wildcard { span: tok.span });
99 }
100
101 let expr = self.parse_expr()?;
102 let mut span = expr.span();
103 let mut alias = None;
104
105 if self.consume_keyword(Keyword::AS) {
106 let (name, alias_span) = self.parse_identifier()?;
107 span = span.union(&alias_span);
108 alias = Some(name);
109 } else if let Token::Word(Word {
110 keyword: Keyword::NoKeyword,
111 ..
112 }) = &self.peek().token
113 {
114 let alias_tok = self.advance();
115 if let Token::Word(Word { value, .. }) = alias_tok.token {
116 span = span.union(&alias_tok.span);
117 alias = Some(value);
118 }
119 }
120
121 Ok(SelectItem::Expr { expr, alias, span })
122 }
123
124 fn parse_table_ref(&mut self) -> Result<TableRef> {
125 let (name, name_span) = self.parse_identifier()?;
126 let mut alias = None;
127 let mut span = name_span;
128
129 if self.consume_keyword(Keyword::AS) {
130 let (a, alias_span) = self.parse_identifier()?;
131 alias = Some(a);
132 span = span.union(&alias_span);
133 } else if let Token::Word(Word {
134 keyword: Keyword::NoKeyword,
135 ..
136 }) = &self.peek().token
137 {
138 let alias_tok = self.advance();
139 if let Token::Word(Word { value, .. }) = alias_tok.token {
140 span = span.union(&alias_tok.span);
141 alias = Some(value);
142 }
143 }
144
145 Ok(TableRef { name, alias, span })
146 }
147
148 fn parse_order_by(&mut self) -> Result<Vec<OrderByExpr>> {
149 let mut items = Vec::new();
150 loop {
151 let expr = self.parse_expr()?;
152 let mut span = expr.span();
153 let mut asc = None;
154 let mut nulls_first = None;
155
156 if let Token::Word(Word { keyword, .. }) = &self.peek().token {
157 match keyword {
158 Keyword::ASC => {
159 let s = self.advance().span;
160 span = span.union(&s);
161 asc = Some(true);
162 }
163 Keyword::DESC => {
164 let s = self.advance().span;
165 span = span.union(&s);
166 asc = Some(false);
167 }
168 _ => {}
169 }
170 }
171
172 if let Token::Word(Word {
173 keyword: Keyword::NULLS,
174 ..
175 }) = &self.peek().token
176 {
177 let nulls_tok = self.advance();
178 let dir_tok = self.expect_token("FIRST or LAST", |t| {
179 matches!(
180 t,
181 Token::Word(Word {
182 keyword: Keyword::FIRST | Keyword::LAST,
183 ..
184 })
185 )
186 })?;
187 nulls_first = Some(matches!(
188 dir_tok.token,
189 Token::Word(Word {
190 keyword: Keyword::FIRST,
191 ..
192 })
193 ));
194 span = span.union(&nulls_tok.span).union(&dir_tok.span);
195 }
196
197 items.push(OrderByExpr {
198 expr,
199 asc,
200 nulls_first,
201 span,
202 });
203
204 if matches!(self.peek().token, Token::Comma) {
205 self.advance();
206 continue;
207 }
208 break;
209 }
210
211 Ok(items)
212 }
213
214 pub fn parse_insert(&mut self) -> Result<Insert> {
215 let start_span = self.expect_keyword("INSERT", Keyword::INSERT)?;
216 self.expect_keyword("INTO", Keyword::INTO)?;
217 let (table, table_span) = self.parse_identifier()?;
218 let mut end_span = table_span;
219 let mut columns = None;
220
221 if matches!(self.peek().token, Token::LParen) {
222 self.advance();
223 let mut cols = Vec::new();
224 loop {
225 let (col, col_span) = self.parse_identifier()?;
226 end_span = end_span.union(&col_span);
227 cols.push(col);
228 if matches!(self.peek().token, Token::Comma) {
229 self.advance();
230 continue;
231 }
232 break;
233 }
234 let close = self
235 .expect_token("')'", |t| matches!(t, Token::RParen))?
236 .span;
237 end_span = end_span.union(&close);
238 columns = Some(cols);
239 }
240
241 self.expect_keyword("VALUES", Keyword::VALUES)?;
242 let mut values = Vec::new();
243 loop {
244 self.expect_token("'('", |t| matches!(t, Token::LParen))?;
245 let mut row = Vec::new();
246 row.push(self.parse_expr()?);
247 while matches!(self.peek().token, Token::Comma) {
248 self.advance();
249 row.push(self.parse_expr()?);
250 }
251 let row_end = self
252 .expect_token("')'", |t| matches!(t, Token::RParen))?
253 .span;
254 end_span = end_span.union(&row_end);
255 values.push(row);
256
257 if matches!(self.peek().token, Token::Comma) {
258 self.advance();
259 continue;
260 }
261 break;
262 }
263
264 let span = start_span.union(&end_span);
265 Ok(Insert {
266 table,
267 columns,
268 values,
269 span,
270 })
271 }
272
273 pub fn parse_update(&mut self) -> Result<Update> {
274 let start_span = self.expect_keyword("UPDATE", Keyword::UPDATE)?;
275 let (table, table_span) = self.parse_identifier()?;
276 self.expect_keyword("SET", Keyword::SET)?;
277
278 let mut assignments = Vec::new();
279 loop {
280 let (column, col_span) = self.parse_identifier()?;
281 self.expect_token("'='", |t| matches!(t, Token::Eq))?;
282 let value = self.parse_expr()?;
283 let span = col_span.union(&value.span());
284 assignments.push(Assignment {
285 column,
286 value,
287 span,
288 });
289
290 if matches!(self.peek().token, Token::Comma) {
291 self.advance();
292 continue;
293 }
294 break;
295 }
296
297 let mut end_span = assignments.last().map(|a| a.span).unwrap_or(table_span);
298
299 let selection = if self.consume_keyword(Keyword::WHERE) {
300 let expr = self.parse_expr()?;
301 end_span = end_span.union(&expr.span());
302 Some(expr)
303 } else {
304 None
305 };
306
307 let span = start_span.union(&end_span);
308 Ok(Update {
309 table,
310 assignments,
311 selection,
312 span,
313 })
314 }
315
316 pub fn parse_delete(&mut self) -> Result<Delete> {
317 let start_span = self.expect_keyword("DELETE", Keyword::DELETE)?;
318 self.expect_keyword("FROM", Keyword::FROM)?;
319 let (table, table_span) = self.parse_identifier()?;
320 let mut end_span = table_span;
321
322 let selection = if self.consume_keyword(Keyword::WHERE) {
323 let expr = self.parse_expr()?;
324 end_span = end_span.union(&expr.span());
325 Some(expr)
326 } else {
327 None
328 };
329
330 let span = start_span.union(&end_span);
331 Ok(Delete {
332 table,
333 selection,
334 span,
335 })
336 }
337}
338
339fn validate_literal_projection(items: &[SelectItem]) -> Result<()> {
340 for item in items {
341 match item {
342 SelectItem::Wildcard { span } => {
343 return Err(ParserError::UnexpectedToken {
344 line: span.start.line,
345 column: span.start.column,
346 expected: "literal expression".to_string(),
347 found: "*".to_string(),
348 });
349 }
350 SelectItem::Expr { expr, .. } => {
351 if expr_contains_column_ref(expr) {
352 return Err(ParserError::UnexpectedToken {
353 line: expr.span.start.line,
354 column: expr.span.start.column,
355 expected: "literal expression".to_string(),
356 found: "column reference".to_string(),
357 });
358 }
359 }
360 }
361 }
362 Ok(())
363}
364
365fn expr_contains_column_ref(expr: &crate::ast::Expr) -> bool {
366 use crate::ast::expr::ExprKind;
367 match &expr.kind {
368 ExprKind::ColumnRef { .. } => true,
369 ExprKind::BinaryOp { left, right, .. } => {
370 expr_contains_column_ref(left) || expr_contains_column_ref(right)
371 }
372 ExprKind::UnaryOp { operand, .. } => expr_contains_column_ref(operand),
373 ExprKind::FunctionCall { args, .. } => args.iter().any(expr_contains_column_ref),
374 ExprKind::Between {
375 expr, low, high, ..
376 } => {
377 expr_contains_column_ref(expr)
378 || expr_contains_column_ref(low)
379 || expr_contains_column_ref(high)
380 }
381 ExprKind::Like {
382 expr,
383 pattern,
384 escape,
385 ..
386 } => {
387 expr_contains_column_ref(expr)
388 || expr_contains_column_ref(pattern)
389 || escape
390 .as_ref()
391 .is_some_and(|expr| expr_contains_column_ref(expr))
392 }
393 ExprKind::InList { expr, list, .. } => {
394 expr_contains_column_ref(expr) || list.iter().any(expr_contains_column_ref)
395 }
396 ExprKind::IsNull { expr, .. } => expr_contains_column_ref(expr),
397 ExprKind::Literal(_) | ExprKind::VectorLiteral(_) => false,
398 }
399}