Skip to main content

reifydb_sql/
parser.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use crate::{
5	Error,
6	ast::*,
7	token::{Keyword, Token},
8};
9
10pub struct Parser {
11	tokens: Vec<Token>,
12	pos: usize,
13}
14
15impl Parser {
16	pub fn new(tokens: Vec<Token>) -> Self {
17		Self {
18			tokens,
19			pos: 0,
20		}
21	}
22
23	pub fn parse(&mut self) -> Result<Statement, Error> {
24		let stmt = match self.peek()? {
25			Token::Keyword(Keyword::With) => self.parse_select()?,
26			Token::Keyword(Keyword::Select) => self.parse_select()?,
27			Token::Keyword(Keyword::Insert) => self.parse_insert()?,
28			Token::Keyword(Keyword::Update) => self.parse_update()?,
29			Token::Keyword(Keyword::Delete) => self.parse_delete()?,
30			Token::Keyword(Keyword::Create) => self.parse_create()?,
31			other => return Err(Error(format!("unexpected token: {other:?}"))),
32		};
33		// Skip optional trailing semicolon
34		if self.pos < self.tokens.len() && self.tokens[self.pos] == Token::Semicolon {
35			self.pos += 1;
36		}
37		Ok(stmt)
38	}
39
40	// ── Helpers ──────────────────────────────────────────────────────────
41
42	fn peek(&self) -> Result<&Token, Error> {
43		self.tokens.get(self.pos).ok_or_else(|| Error("unexpected end of input".into()))
44	}
45
46	fn advance(&mut self) -> Result<Token, Error> {
47		if self.pos < self.tokens.len() {
48			let tok = self.tokens[self.pos].clone();
49			self.pos += 1;
50			Ok(tok)
51		} else {
52			Err(Error("unexpected end of input".into()))
53		}
54	}
55
56	fn expect_keyword(&mut self, kw: Keyword) -> Result<(), Error> {
57		let tok = self.advance()?;
58		if tok == Token::Keyword(kw.clone()) {
59			Ok(())
60		} else {
61			Err(Error(format!("expected {kw:?}, got {tok:?}")))
62		}
63	}
64
65	fn expect_token(&mut self, expected: Token) -> Result<(), Error> {
66		let tok = self.advance()?;
67		if tok == expected {
68			Ok(())
69		} else {
70			Err(Error(format!("expected {expected:?}, got {tok:?}")))
71		}
72	}
73
74	fn at_keyword(&self, kw: &Keyword) -> bool {
75		matches!(self.tokens.get(self.pos), Some(Token::Keyword(k)) if k == kw)
76	}
77
78	fn at_token(&self, t: &Token) -> bool {
79		matches!(self.tokens.get(self.pos), Some(tok) if tok == t)
80	}
81
82	fn is_eof(&self) -> bool {
83		self.pos >= self.tokens.len()
84	}
85
86	fn expect_ident(&mut self) -> Result<String, Error> {
87		let tok = self.advance()?;
88		match tok {
89			Token::Ident(name) => Ok(name),
90			// Allow certain keywords to be used as identifiers (common in SQL)
91			Token::Keyword(kw) => Ok(keyword_to_string(&kw)),
92			_ => Err(Error(format!("expected identifier, got {tok:?}"))),
93		}
94	}
95
96	// ── SELECT ──────────────────────────────────────────────────────────
97
98	fn parse_select(&mut self) -> Result<Statement, Error> {
99		let ctes = if self.at_keyword(&Keyword::With) {
100			self.parse_cte_list()?
101		} else {
102			vec![]
103		};
104
105		self.expect_keyword(Keyword::Select)?;
106
107		let distinct = if self.at_keyword(&Keyword::Distinct) {
108			self.advance()?;
109			true
110		} else {
111			false
112		};
113
114		let columns = self.parse_select_columns()?;
115
116		let from = if self.at_keyword(&Keyword::From) {
117			self.advance()?;
118			Some(self.parse_from_clause()?)
119		} else {
120			None
121		};
122
123		let mut joins = Vec::new();
124		while self.parse_join_if_present()? {
125			let join = self.finish_parse_join()?;
126			joins.push(join);
127		}
128
129		let where_clause = if self.at_keyword(&Keyword::Where) {
130			self.advance()?;
131			Some(self.parse_expr()?)
132		} else {
133			None
134		};
135
136		let group_by = if self.at_keyword(&Keyword::Group) {
137			self.advance()?;
138			self.expect_keyword(Keyword::By)?;
139			self.parse_expr_list()?
140		} else {
141			vec![]
142		};
143
144		let having = if self.at_keyword(&Keyword::Having) {
145			self.advance()?;
146			Some(self.parse_expr()?)
147		} else {
148			None
149		};
150
151		let order_by = if self.at_keyword(&Keyword::Order) {
152			self.advance()?;
153			self.expect_keyword(Keyword::By)?;
154			self.parse_order_by_list()?
155		} else {
156			vec![]
157		};
158
159		let limit = if self.at_keyword(&Keyword::Limit) {
160			self.advance()?;
161			Some(self.parse_u64()?)
162		} else {
163			None
164		};
165
166		let offset = if self.at_keyword(&Keyword::Offset) {
167			self.advance()?;
168			Some(self.parse_u64()?)
169		} else {
170			None
171		};
172
173		Ok(Statement::Select(SelectStatement {
174			ctes,
175			distinct,
176			columns,
177			from,
178			joins,
179			where_clause,
180			group_by,
181			having,
182			order_by,
183			limit,
184			offset,
185		}))
186	}
187
188	fn parse_cte_list(&mut self) -> Result<Vec<CteDefinition>, Error> {
189		self.expect_keyword(Keyword::With)?;
190		if self.at_keyword(&Keyword::Recursive) {
191			return Err(Error("recursive CTEs are not supported".into()));
192		}
193		let mut ctes = Vec::new();
194		loop {
195			let name = self.expect_ident()?;
196			self.expect_keyword(Keyword::As)?;
197			self.expect_token(Token::OpenParen)?;
198			let stmt = self.parse_select()?;
199			let query = match stmt {
200				Statement::Select(sel) => sel,
201				_ => return Err(Error("expected SELECT in CTE definition".into())),
202			};
203			self.expect_token(Token::CloseParen)?;
204			ctes.push(CteDefinition {
205				name,
206				query,
207			});
208			if self.at_token(&Token::Comma) {
209				self.advance()?;
210			} else {
211				break;
212			}
213		}
214		Ok(ctes)
215	}
216
217	fn parse_select_columns(&mut self) -> Result<Vec<SelectColumn>, Error> {
218		let mut cols = Vec::new();
219		loop {
220			if self.at_token(&Token::Asterisk) {
221				self.advance()?;
222				cols.push(SelectColumn::AllColumns);
223			} else if self.is_eof()
224				|| self.at_keyword(&Keyword::From)
225				|| self.at_keyword(&Keyword::Where)
226				|| self.at_keyword(&Keyword::Order)
227				|| self.at_keyword(&Keyword::Limit)
228				|| self.at_keyword(&Keyword::Group)
229				|| self.at_keyword(&Keyword::Having)
230				|| self.at_token(&Token::Semicolon)
231			{
232				break;
233			} else {
234				let expr = self.parse_expr()?;
235				let alias = if self.at_keyword(&Keyword::As) {
236					self.advance()?;
237					Some(self.expect_ident()?)
238				} else {
239					None
240				};
241				cols.push(SelectColumn::Expr {
242					expr,
243					alias,
244				});
245			}
246
247			if self.at_token(&Token::Comma) {
248				self.advance()?;
249			} else {
250				break;
251			}
252		}
253		Ok(cols)
254	}
255
256	fn parse_from_clause(&mut self) -> Result<FromClause, Error> {
257		if self.at_token(&Token::OpenParen) {
258			// Could be a subquery
259			self.advance()?;
260			if self.at_keyword(&Keyword::Select) {
261				let stmt = self.parse_select()?;
262				self.expect_token(Token::CloseParen)?;
263				if let Statement::Select(sel) = stmt {
264					return Ok(FromClause::Subquery(Box::new(sel)));
265				}
266			}
267			return Err(Error("expected subquery after '('".into()));
268		}
269
270		let name = self.expect_ident()?;
271		if self.at_token(&Token::Dot) {
272			self.advance()?;
273			let table = self.expect_ident()?;
274			Ok(FromClause::Table {
275				schema: Some(name),
276				name: table,
277			})
278		} else {
279			Ok(FromClause::Table {
280				name,
281				schema: None,
282			})
283		}
284	}
285
286	// ── JOIN ────────────────────────────────────────────────────────────
287
288	/// Check if the next tokens form a JOIN clause.  Returns true and
289	/// consumes the join-type keywords (INNER/LEFT and JOIN) if present.
290	fn parse_join_if_present(&mut self) -> Result<bool, Error> {
291		if self.is_eof() {
292			return Ok(false);
293		}
294		// Bare JOIN
295		if self.at_keyword(&Keyword::Join) {
296			return Ok(true);
297		}
298		// INNER JOIN / LEFT JOIN
299		if self.at_keyword(&Keyword::Inner) || self.at_keyword(&Keyword::Left) {
300			if let Some(Token::Keyword(Keyword::Join)) = self.tokens.get(self.pos + 1) {
301				return Ok(true);
302			}
303		}
304		Ok(false)
305	}
306
307	fn finish_parse_join(&mut self) -> Result<JoinClause, Error> {
308		let join_type = if self.at_keyword(&Keyword::Left) {
309			self.advance()?;
310			self.expect_keyword(Keyword::Join)?;
311			JoinType::Left
312		} else if self.at_keyword(&Keyword::Inner) {
313			self.advance()?;
314			self.expect_keyword(Keyword::Join)?;
315			JoinType::Inner
316		} else {
317			self.expect_keyword(Keyword::Join)?;
318			JoinType::Inner
319		};
320
321		let table = self.parse_from_clause()?;
322		let table_alias = if self.at_keyword(&Keyword::As) {
323			self.advance()?;
324			Some(self.expect_ident()?)
325		} else if !self.is_eof() && matches!(self.peek()?, Token::Ident(_)) && !self.at_keyword(&Keyword::On) {
326			Some(self.expect_ident()?)
327		} else {
328			None
329		};
330
331		self.expect_keyword(Keyword::On)?;
332		let on = self.parse_expr()?;
333
334		Ok(JoinClause {
335			join_type,
336			table,
337			table_alias,
338			on,
339		})
340	}
341
342	// ── INSERT ──────────────────────────────────────────────────────────
343
344	fn parse_insert(&mut self) -> Result<Statement, Error> {
345		self.expect_keyword(Keyword::Insert)?;
346		self.expect_keyword(Keyword::Into)?;
347
348		let (schema, table) = self.parse_table_name()?;
349
350		let columns = if self.at_token(&Token::OpenParen) {
351			self.advance()?;
352			let cols = self.parse_ident_list()?;
353			self.expect_token(Token::CloseParen)?;
354			cols
355		} else {
356			vec![]
357		};
358
359		self.expect_keyword(Keyword::Values)?;
360
361		let mut values = Vec::new();
362		loop {
363			self.expect_token(Token::OpenParen)?;
364			let row = self.parse_expr_list()?;
365			self.expect_token(Token::CloseParen)?;
366			values.push(row);
367			if self.at_token(&Token::Comma) {
368				self.advance()?;
369			} else {
370				break;
371			}
372		}
373
374		Ok(Statement::Insert(InsertStatement {
375			table,
376			schema,
377			columns,
378			values,
379		}))
380	}
381
382	// ── UPDATE ──────────────────────────────────────────────────────────
383
384	fn parse_update(&mut self) -> Result<Statement, Error> {
385		self.expect_keyword(Keyword::Update)?;
386		let (schema, table) = self.parse_table_name()?;
387		self.expect_keyword(Keyword::Set)?;
388
389		let mut assignments = Vec::new();
390		loop {
391			let col = self.expect_ident()?;
392			self.expect_token(Token::Eq)?;
393			let val = self.parse_expr()?;
394			assignments.push((col, val));
395			if self.at_token(&Token::Comma) {
396				self.advance()?;
397			} else {
398				break;
399			}
400		}
401
402		let where_clause = if self.at_keyword(&Keyword::Where) {
403			self.advance()?;
404			Some(self.parse_expr()?)
405		} else {
406			None
407		};
408
409		Ok(Statement::Update(UpdateStatement {
410			table,
411			schema,
412			assignments,
413			where_clause,
414		}))
415	}
416
417	// ── DELETE ──────────────────────────────────────────────────────────
418
419	fn parse_delete(&mut self) -> Result<Statement, Error> {
420		self.expect_keyword(Keyword::Delete)?;
421		self.expect_keyword(Keyword::From)?;
422		let (schema, table) = self.parse_table_name()?;
423
424		let where_clause = if self.at_keyword(&Keyword::Where) {
425			self.advance()?;
426			Some(self.parse_expr()?)
427		} else {
428			None
429		};
430
431		Ok(Statement::Delete(DeleteStatement {
432			table,
433			schema,
434			where_clause,
435		}))
436	}
437
438	// ── CREATE TABLE ────────────────────────────────────────────────────
439
440	fn parse_create(&mut self) -> Result<Statement, Error> {
441		self.expect_keyword(Keyword::Create)?;
442		self.expect_keyword(Keyword::Table)?;
443		let (schema, table) = self.parse_table_name()?;
444
445		self.expect_token(Token::OpenParen)?;
446		let mut columns = Vec::new();
447		let mut primary_key = Vec::new();
448		loop {
449			if self.at_token(&Token::CloseParen) {
450				break;
451			}
452			// Check for PRIMARY KEY(...) table constraint
453			if self.at_keyword(&Keyword::Primary) {
454				self.advance()?;
455				self.expect_keyword(Keyword::Key)?;
456				self.expect_token(Token::OpenParen)?;
457				primary_key = self.parse_ident_list()?;
458				self.expect_token(Token::CloseParen)?;
459				if self.at_token(&Token::Comma) {
460					self.advance()?;
461				}
462				continue;
463			}
464			let name = self.expect_ident()?;
465			let data_type = self.parse_sql_type()?;
466			let nullable = if self.at_keyword(&Keyword::Not) {
467				self.advance()?;
468				self.expect_keyword(Keyword::Null)?;
469				false
470			} else if self.at_keyword(&Keyword::Null) {
471				self.advance()?;
472				true
473			} else {
474				true
475			};
476			columns.push(ColumnDef {
477				name,
478				data_type,
479				nullable,
480			});
481			if self.at_token(&Token::Comma) {
482				self.advance()?;
483			} else {
484				break;
485			}
486		}
487		self.expect_token(Token::CloseParen)?;
488
489		Ok(Statement::CreateTable(CreateTableStatement {
490			table,
491			schema,
492			columns,
493			primary_key,
494		}))
495	}
496
497	// ── Type parsing ────────────────────────────────────────────────────
498
499	fn parse_sql_type(&mut self) -> Result<SqlType, Error> {
500		let tok = self.advance()?;
501		match tok {
502			Token::Keyword(Keyword::Int) => Ok(SqlType::Int),
503			Token::Keyword(Keyword::Int2) => Ok(SqlType::Int2),
504			Token::Keyword(Keyword::Int4) => Ok(SqlType::Int4),
505			Token::Keyword(Keyword::Int8) => Ok(SqlType::Int8),
506			Token::Keyword(Keyword::Smallint) => Ok(SqlType::Smallint),
507			Token::Keyword(Keyword::Integer) => Ok(SqlType::Integer),
508			Token::Keyword(Keyword::Bigint) => Ok(SqlType::Bigint),
509			Token::Keyword(Keyword::Float4) => Ok(SqlType::Float4),
510			Token::Keyword(Keyword::Float8) => Ok(SqlType::Float8),
511			Token::Keyword(Keyword::Real) => Ok(SqlType::Real),
512			Token::Keyword(Keyword::Double) => {
513				// DOUBLE PRECISION
514				if self.at_keyword(&Keyword::Precision) {
515					self.advance()?;
516				}
517				Ok(SqlType::Double)
518			}
519			Token::Keyword(Keyword::Boolean) => Ok(SqlType::Boolean),
520			Token::Keyword(Keyword::Bool) => Ok(SqlType::Bool),
521			Token::Keyword(Keyword::Text) => Ok(SqlType::Text),
522			Token::Keyword(Keyword::Utf8) => Ok(SqlType::Utf8),
523			Token::Keyword(Keyword::Blob) => Ok(SqlType::Blob),
524			Token::Keyword(Keyword::Varchar) => {
525				let len = if self.at_token(&Token::OpenParen) {
526					self.advance()?;
527					let n = self.parse_u64()?;
528					self.expect_token(Token::CloseParen)?;
529					Some(n)
530				} else {
531					None
532				};
533				Ok(SqlType::Varchar(len))
534			}
535			Token::Keyword(Keyword::Char) => {
536				let len = if self.at_token(&Token::OpenParen) {
537					self.advance()?;
538					let n = self.parse_u64()?;
539					self.expect_token(Token::CloseParen)?;
540					Some(n)
541				} else {
542					None
543				};
544				Ok(SqlType::Char(len))
545			}
546			_ => Err(Error(format!("expected SQL type, got {tok:?}"))),
547		}
548	}
549
550	// ── Expression parsing (Pratt-style precedence) ─────────────────────
551
552	fn parse_expr(&mut self) -> Result<Expr, Error> {
553		self.parse_or()
554	}
555
556	fn parse_or(&mut self) -> Result<Expr, Error> {
557		let mut left = self.parse_and()?;
558		while self.at_keyword(&Keyword::Or) {
559			self.advance()?;
560			let right = self.parse_and()?;
561			left = Expr::BinaryOp {
562				left: Box::new(left),
563				op: BinaryOp::Or,
564				right: Box::new(right),
565			};
566		}
567		Ok(left)
568	}
569
570	fn parse_and(&mut self) -> Result<Expr, Error> {
571		let mut left = self.parse_not()?;
572		while self.at_keyword(&Keyword::And) {
573			self.advance()?;
574			let right = self.parse_not()?;
575			left = Expr::BinaryOp {
576				left: Box::new(left),
577				op: BinaryOp::And,
578				right: Box::new(right),
579			};
580		}
581		Ok(left)
582	}
583
584	fn parse_not(&mut self) -> Result<Expr, Error> {
585		if self.at_keyword(&Keyword::Not) {
586			self.advance()?;
587			let expr = self.parse_not()?;
588			Ok(Expr::UnaryOp {
589				op: UnaryOp::Not,
590				expr: Box::new(expr),
591			})
592		} else {
593			self.parse_comparison()
594		}
595	}
596
597	fn parse_comparison(&mut self) -> Result<Expr, Error> {
598		let mut left = self.parse_addition()?;
599
600		// IS NULL / IS NOT NULL
601		if self.at_keyword(&Keyword::Is) {
602			self.advance()?;
603			if self.at_keyword(&Keyword::Not) {
604				self.advance()?;
605				self.expect_keyword(Keyword::Null)?;
606				return Ok(Expr::IsNull {
607					expr: Box::new(left),
608					negated: true,
609				});
610			} else {
611				self.expect_keyword(Keyword::Null)?;
612				return Ok(Expr::IsNull {
613					expr: Box::new(left),
614					negated: false,
615				});
616			}
617		}
618
619		// NOT BETWEEN / BETWEEN ... AND ...
620		if self.at_keyword(&Keyword::Not)
621			&& matches!(self.tokens.get(self.pos + 1), Some(Token::Keyword(Keyword::Between)))
622		{
623			self.advance()?; // NOT
624			self.advance()?; // BETWEEN
625			let low = self.parse_addition()?;
626			self.expect_keyword(Keyword::And)?;
627			let high = self.parse_addition()?;
628			return Ok(Expr::Between {
629				expr: Box::new(left),
630				low: Box::new(low),
631				high: Box::new(high),
632				negated: true,
633			});
634		}
635
636		if self.at_keyword(&Keyword::Between) {
637			self.advance()?;
638			let low = self.parse_addition()?;
639			self.expect_keyword(Keyword::And)?;
640			let high = self.parse_addition()?;
641			return Ok(Expr::Between {
642				expr: Box::new(left),
643				low: Box::new(low),
644				high: Box::new(high),
645				negated: false,
646			});
647		}
648
649		// NOT IN / IN (...)
650		if self.at_keyword(&Keyword::Not)
651			&& matches!(self.tokens.get(self.pos + 1), Some(Token::Keyword(Keyword::In)))
652		{
653			self.advance()?; // NOT
654			self.advance()?; // IN
655			self.expect_token(Token::OpenParen)?;
656			let list = self.parse_expr_list()?;
657			self.expect_token(Token::CloseParen)?;
658			return Ok(Expr::InList {
659				expr: Box::new(left),
660				list,
661				negated: true,
662			});
663		}
664
665		if self.at_keyword(&Keyword::In) {
666			self.advance()?;
667			self.expect_token(Token::OpenParen)?;
668			let list = self.parse_expr_list()?;
669			self.expect_token(Token::CloseParen)?;
670			return Ok(Expr::InList {
671				expr: Box::new(left),
672				list,
673				negated: false,
674			});
675		}
676
677		// Comparison operators
678		let op = match self.tokens.get(self.pos) {
679			Some(Token::Eq) => Some(BinaryOp::Eq),
680			Some(Token::NotEq) => Some(BinaryOp::NotEq),
681			Some(Token::Lt) => Some(BinaryOp::Lt),
682			Some(Token::Gt) => Some(BinaryOp::Gt),
683			Some(Token::LtEq) => Some(BinaryOp::LtEq),
684			Some(Token::GtEq) => Some(BinaryOp::GtEq),
685			_ => None,
686		};
687		if let Some(op) = op {
688			self.advance()?;
689			let right = self.parse_addition()?;
690			left = Expr::BinaryOp {
691				left: Box::new(left),
692				op,
693				right: Box::new(right),
694			};
695		}
696
697		Ok(left)
698	}
699
700	fn parse_addition(&mut self) -> Result<Expr, Error> {
701		let mut left = self.parse_multiplication()?;
702		loop {
703			let op = match self.tokens.get(self.pos) {
704				Some(Token::Plus) => Some(BinaryOp::Add),
705				Some(Token::Minus) => Some(BinaryOp::Sub),
706				_ => None,
707			};
708			if let Some(op) = op {
709				self.advance()?;
710				let right = self.parse_multiplication()?;
711				left = Expr::BinaryOp {
712					left: Box::new(left),
713					op,
714					right: Box::new(right),
715				};
716			} else {
717				break;
718			}
719		}
720		Ok(left)
721	}
722
723	fn parse_multiplication(&mut self) -> Result<Expr, Error> {
724		let mut left = self.parse_unary()?;
725		loop {
726			let op = match self.tokens.get(self.pos) {
727				Some(Token::Asterisk) => Some(BinaryOp::Mul),
728				Some(Token::Slash) => Some(BinaryOp::Div),
729				Some(Token::Percent) => Some(BinaryOp::Mod),
730				_ => None,
731			};
732			if let Some(op) = op {
733				self.advance()?;
734				let right = self.parse_unary()?;
735				left = Expr::BinaryOp {
736					left: Box::new(left),
737					op,
738					right: Box::new(right),
739				};
740			} else {
741				break;
742			}
743		}
744		Ok(left)
745	}
746
747	fn parse_unary(&mut self) -> Result<Expr, Error> {
748		if self.at_token(&Token::Minus) {
749			self.advance()?;
750			let expr = self.parse_primary()?;
751			return Ok(Expr::UnaryOp {
752				op: UnaryOp::Neg,
753				expr: Box::new(expr),
754			});
755		}
756		self.parse_primary()
757	}
758
759	fn parse_primary(&mut self) -> Result<Expr, Error> {
760		let tok = self.peek()?.clone();
761		match tok {
762			Token::Integer(n) => {
763				self.advance()?;
764				Ok(Expr::IntegerLiteral(n))
765			}
766			Token::Float(f) => {
767				self.advance()?;
768				Ok(Expr::FloatLiteral(f))
769			}
770			Token::StringLit(s) => {
771				self.advance()?;
772				Ok(Expr::StringLiteral(s))
773			}
774			Token::Keyword(Keyword::True) => {
775				self.advance()?;
776				Ok(Expr::BoolLiteral(true))
777			}
778			Token::Keyword(Keyword::False) => {
779				self.advance()?;
780				Ok(Expr::BoolLiteral(false))
781			}
782			Token::Keyword(Keyword::Null) => {
783				self.advance()?;
784				Ok(Expr::Null)
785			}
786			Token::Keyword(Keyword::Cast) => self.parse_cast_expr(),
787			// Aggregate function keywords
788			Token::Keyword(Keyword::Count)
789			| Token::Keyword(Keyword::Sum)
790			| Token::Keyword(Keyword::Avg)
791			| Token::Keyword(Keyword::Min)
792			| Token::Keyword(Keyword::Max) => {
793				let name = keyword_to_string(match &self.advance()? {
794					Token::Keyword(kw) => kw,
795					_ => unreachable!(),
796				});
797				self.expect_token(Token::OpenParen)?;
798				let args = if self.at_token(&Token::Asterisk) {
799					self.advance()?;
800					vec![Expr::Identifier("*".into())]
801				} else {
802					self.parse_expr_list()?
803				};
804				self.expect_token(Token::CloseParen)?;
805				Ok(Expr::FunctionCall {
806					name,
807					args,
808				})
809			}
810			Token::OpenParen => {
811				self.advance()?;
812				let expr = self.parse_expr()?;
813				self.expect_token(Token::CloseParen)?;
814				Ok(Expr::Nested(Box::new(expr)))
815			}
816			Token::Ident(_) => {
817				let name = self.expect_ident()?;
818				// Check for qualified identifier (table.column)
819				if self.at_token(&Token::Dot) {
820					self.advance()?;
821					let col = self.expect_ident()?;
822					// Check for function call on qualified name
823					if self.at_token(&Token::OpenParen) {
824						self.advance()?;
825						let args = if self.at_token(&Token::CloseParen) {
826							vec![]
827						} else if self.at_token(&Token::Asterisk) {
828							self.advance()?;
829							vec![Expr::Identifier("*".into())]
830						} else {
831							self.parse_expr_list()?
832						};
833						self.expect_token(Token::CloseParen)?;
834						Ok(Expr::FunctionCall {
835							name: format!("{name}.{col}"),
836							args,
837						})
838					} else {
839						Ok(Expr::QualifiedIdentifier(name, col))
840					}
841				}
842				// Check for function call
843				else if self.at_token(&Token::OpenParen) {
844					self.advance()?;
845					let args = if self.at_token(&Token::CloseParen) {
846						vec![]
847					} else if self.at_token(&Token::Asterisk) {
848						self.advance()?;
849						vec![Expr::Identifier("*".into())]
850					} else {
851						self.parse_expr_list()?
852					};
853					self.expect_token(Token::CloseParen)?;
854					Ok(Expr::FunctionCall {
855						name,
856						args,
857					})
858				} else {
859					Ok(Expr::Identifier(name))
860				}
861			}
862			_ => Err(Error(format!("unexpected token in expression: {tok:?}"))),
863		}
864	}
865
866	fn parse_cast_expr(&mut self) -> Result<Expr, Error> {
867		self.expect_keyword(Keyword::Cast)?;
868		self.expect_token(Token::OpenParen)?;
869		let expr = self.parse_expr()?;
870		self.expect_keyword(Keyword::As)?;
871		let data_type = self.parse_sql_type()?;
872		self.expect_token(Token::CloseParen)?;
873		Ok(Expr::Cast {
874			expr: Box::new(expr),
875			data_type,
876		})
877	}
878
879	// ── Utility ─────────────────────────────────────────────────────────
880
881	fn parse_expr_list(&mut self) -> Result<Vec<Expr>, Error> {
882		let mut exprs = Vec::new();
883		exprs.push(self.parse_expr()?);
884		while self.at_token(&Token::Comma) {
885			self.advance()?;
886			exprs.push(self.parse_expr()?);
887		}
888		Ok(exprs)
889	}
890
891	fn parse_ident_list(&mut self) -> Result<Vec<String>, Error> {
892		let mut names = Vec::new();
893		names.push(self.expect_ident()?);
894		while self.at_token(&Token::Comma) {
895			self.advance()?;
896			names.push(self.expect_ident()?);
897		}
898		Ok(names)
899	}
900
901	fn parse_order_by_list(&mut self) -> Result<Vec<OrderByItem>, Error> {
902		let mut items = Vec::new();
903		loop {
904			let expr = self.parse_expr()?;
905			let direction = if self.at_keyword(&Keyword::Desc) {
906				self.advance()?;
907				OrderDirection::Desc
908			} else {
909				if self.at_keyword(&Keyword::Asc) {
910					self.advance()?;
911				}
912				OrderDirection::Asc
913			};
914			items.push(OrderByItem {
915				expr,
916				direction,
917			});
918			if self.at_token(&Token::Comma) {
919				self.advance()?;
920			} else {
921				break;
922			}
923		}
924		Ok(items)
925	}
926
927	fn parse_u64(&mut self) -> Result<u64, Error> {
928		let tok = self.advance()?;
929		match tok {
930			Token::Integer(n) if n >= 0 => Ok(n as u64),
931			_ => Err(Error(format!("expected positive integer, got {tok:?}"))),
932		}
933	}
934
935	fn parse_table_name(&mut self) -> Result<(Option<String>, String), Error> {
936		let name = self.expect_ident()?;
937		if self.at_token(&Token::Dot) {
938			self.advance()?;
939			let table = self.expect_ident()?;
940			Ok((Some(name), table))
941		} else {
942			Ok((None, name))
943		}
944	}
945}
946
947fn keyword_to_string(kw: &Keyword) -> String {
948	match kw {
949		Keyword::Select => "SELECT",
950		Keyword::From => "FROM",
951		Keyword::Where => "WHERE",
952		Keyword::And => "AND",
953		Keyword::Or => "OR",
954		Keyword::Not => "NOT",
955		Keyword::As => "AS",
956		Keyword::Order => "ORDER",
957		Keyword::By => "BY",
958		Keyword::Asc => "ASC",
959		Keyword::Desc => "DESC",
960		Keyword::Limit => "LIMIT",
961		Keyword::Offset => "OFFSET",
962		Keyword::Group => "GROUP",
963		Keyword::Having => "HAVING",
964		Keyword::Distinct => "DISTINCT",
965		Keyword::Insert => "INSERT",
966		Keyword::Into => "INTO",
967		Keyword::Values => "VALUES",
968		Keyword::Update => "UPDATE",
969		Keyword::Set => "SET",
970		Keyword::Delete => "DELETE",
971		Keyword::Create => "CREATE",
972		Keyword::Table => "TABLE",
973		Keyword::Join => "JOIN",
974		Keyword::Inner => "INNER",
975		Keyword::Left => "LEFT",
976		Keyword::Right => "RIGHT",
977		Keyword::On => "ON",
978		Keyword::Null => "NULL",
979		Keyword::True => "true",
980		Keyword::False => "false",
981		Keyword::Is => "IS",
982		Keyword::In => "IN",
983		Keyword::Between => "BETWEEN",
984		Keyword::Cast => "CAST",
985		Keyword::Count => "COUNT",
986		Keyword::Sum => "SUM",
987		Keyword::Avg => "AVG",
988		Keyword::Min => "MIN",
989		Keyword::Max => "MAX",
990		Keyword::Int => "INT",
991		Keyword::Int2 => "INT2",
992		Keyword::Int4 => "INT4",
993		Keyword::Int8 => "INT8",
994		Keyword::Smallint => "SMALLINT",
995		Keyword::Integer => "INTEGER",
996		Keyword::Bigint => "BIGINT",
997		Keyword::Float4 => "FLOAT4",
998		Keyword::Float8 => "FLOAT8",
999		Keyword::Real => "REAL",
1000		Keyword::Double => "DOUBLE",
1001		Keyword::Precision => "PRECISION",
1002		Keyword::Boolean => "BOOLEAN",
1003		Keyword::Bool => "BOOL",
1004		Keyword::Varchar => "VARCHAR",
1005		Keyword::Text => "TEXT",
1006		Keyword::Char => "CHAR",
1007		Keyword::Utf8 => "UTF8",
1008		Keyword::Blob => "BLOB",
1009		Keyword::Primary => "PRIMARY",
1010		Keyword::Key => "KEY",
1011		Keyword::With => "WITH",
1012		Keyword::Recursive => "RECURSIVE",
1013	}
1014	.into()
1015}
1016
1017#[cfg(test)]
1018mod tests {
1019	use super::*;
1020	use crate::token::tokenize;
1021
1022	#[test]
1023	fn test_parse_simple_select() {
1024		let tokens = tokenize("SELECT id, name FROM users").unwrap();
1025		let stmt = Parser::new(tokens).parse().unwrap();
1026		match stmt {
1027			Statement::Select(sel) => {
1028				assert_eq!(sel.columns.len(), 2);
1029				assert!(sel.from.is_some());
1030			}
1031			_ => panic!("expected select"),
1032		}
1033	}
1034
1035	#[test]
1036	fn test_parse_select_star() {
1037		let tokens = tokenize("SELECT * FROM users").unwrap();
1038		let stmt = Parser::new(tokens).parse().unwrap();
1039		match stmt {
1040			Statement::Select(sel) => {
1041				assert!(matches!(sel.columns[0], SelectColumn::AllColumns));
1042			}
1043			_ => panic!("expected select"),
1044		}
1045	}
1046
1047	#[test]
1048	fn test_parse_where() {
1049		let tokens = tokenize("SELECT * FROM users WHERE age > 18").unwrap();
1050		let stmt = Parser::new(tokens).parse().unwrap();
1051		match stmt {
1052			Statement::Select(sel) => {
1053				assert!(sel.where_clause.is_some());
1054			}
1055			_ => panic!("expected select"),
1056		}
1057	}
1058
1059	#[test]
1060	fn test_parse_insert() {
1061		let tokens = tokenize("INSERT INTO users (id, name) VALUES (1, 'Alice')").unwrap();
1062		let stmt = Parser::new(tokens).parse().unwrap();
1063		match stmt {
1064			Statement::Insert(ins) => {
1065				assert_eq!(ins.table, "users");
1066				assert_eq!(ins.columns.len(), 2);
1067				assert_eq!(ins.values.len(), 1);
1068			}
1069			_ => panic!("expected insert"),
1070		}
1071	}
1072}