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			Token::Keyword(Keyword::Drop) => self.parse_drop()?,
32			other => return Err(Error(format!("unexpected token: {other:?}"))),
33		};
34		// Skip optional trailing semicolon
35		if self.pos < self.tokens.len() && self.tokens[self.pos] == Token::Semicolon {
36			self.pos += 1;
37		}
38		Ok(stmt)
39	}
40
41	// ── Helpers ──────────────────────────────────────────────────────────
42
43	fn peek(&self) -> Result<&Token, Error> {
44		self.tokens.get(self.pos).ok_or_else(|| Error("unexpected end of input".into()))
45	}
46
47	fn advance(&mut self) -> Result<Token, Error> {
48		if self.pos < self.tokens.len() {
49			let tok = self.tokens[self.pos].clone();
50			self.pos += 1;
51			Ok(tok)
52		} else {
53			Err(Error("unexpected end of input".into()))
54		}
55	}
56
57	fn expect_keyword(&mut self, kw: Keyword) -> Result<(), Error> {
58		let tok = self.advance()?;
59		if tok == Token::Keyword(kw.clone()) {
60			Ok(())
61		} else {
62			Err(Error(format!("expected {kw:?}, got {tok:?}")))
63		}
64	}
65
66	fn expect_token(&mut self, expected: Token) -> Result<(), Error> {
67		let tok = self.advance()?;
68		if tok == expected {
69			Ok(())
70		} else {
71			Err(Error(format!("expected {expected:?}, got {tok:?}")))
72		}
73	}
74
75	fn at_keyword(&self, kw: &Keyword) -> bool {
76		matches!(self.tokens.get(self.pos), Some(Token::Keyword(k)) if k == kw)
77	}
78
79	fn at_token(&self, t: &Token) -> bool {
80		matches!(self.tokens.get(self.pos), Some(tok) if tok == t)
81	}
82
83	fn is_eof(&self) -> bool {
84		self.pos >= self.tokens.len()
85	}
86
87	fn expect_ident(&mut self) -> Result<String, Error> {
88		let tok = self.advance()?;
89		match tok {
90			Token::Ident(name) => Ok(name),
91			// Allow certain keywords to be used as identifiers (common in SQL)
92			Token::Keyword(kw) => Ok(keyword_to_string(&kw)),
93			_ => Err(Error(format!("expected identifier, got {tok:?}"))),
94		}
95	}
96
97	/// Check if next token is an identifier-like token (not a structural keyword).
98	/// Used for optional alias detection.
99	fn is_ident_like(&self) -> bool {
100		match self.tokens.get(self.pos) {
101			Some(Token::Ident(_)) => true,
102			Some(Token::Keyword(kw)) => !is_structural_keyword(kw),
103			_ => false,
104		}
105	}
106
107	// ── SELECT ──────────────────────────────────────────────────────────
108
109	fn parse_select(&mut self) -> Result<Statement, Error> {
110		let sel = self.parse_select_statement()?;
111		Ok(Statement::Select(sel))
112	}
113
114	fn parse_select_statement(&mut self) -> Result<SelectStatement, Error> {
115		let ctes = if self.at_keyword(&Keyword::With) {
116			self.parse_cte_list()?
117		} else {
118			vec![]
119		};
120
121		self.expect_keyword(Keyword::Select)?;
122
123		let distinct = if self.at_keyword(&Keyword::Distinct) {
124			self.advance()?;
125			true
126		} else {
127			false
128		};
129
130		let columns = self.parse_select_columns()?;
131
132		let mut from = None;
133		let mut joins = Vec::new();
134
135		if self.at_keyword(&Keyword::From) {
136			self.advance()?;
137			let (first_from, _first_alias) = self.parse_from_item()?;
138			from = Some(first_from);
139
140			// Handle comma-separated tables (implicit cross join)
141			while self.at_token(&Token::Comma) {
142				self.advance()?;
143				let (extra_from, extra_alias) = self.parse_from_item()?;
144				let alias = extra_alias.or_else(|| match &extra_from {
145					FromClause::Table {
146						name,
147						..
148					} => Some(name.clone()),
149					_ => None,
150				});
151				joins.push(JoinClause {
152					join_type: JoinType::Cross,
153					table: extra_from,
154					table_alias: alias,
155					on: Expr::BoolLiteral(true),
156				});
157			}
158		}
159		while self.parse_join_if_present()? {
160			let join = self.finish_parse_join()?;
161			joins.push(join);
162		}
163
164		let where_clause = if self.at_keyword(&Keyword::Where) {
165			self.advance()?;
166			Some(self.parse_expr()?)
167		} else {
168			None
169		};
170
171		let group_by = if self.at_keyword(&Keyword::Group) {
172			self.advance()?;
173			self.expect_keyword(Keyword::By)?;
174			self.parse_expr_list()?
175		} else {
176			vec![]
177		};
178
179		let having = if self.at_keyword(&Keyword::Having) {
180			self.advance()?;
181			Some(self.parse_expr()?)
182		} else {
183			None
184		};
185
186		let order_by = if self.at_keyword(&Keyword::Order) {
187			self.advance()?;
188			self.expect_keyword(Keyword::By)?;
189			self.parse_order_by_list()?
190		} else {
191			vec![]
192		};
193
194		let limit = if self.at_keyword(&Keyword::Limit) {
195			self.advance()?;
196			Some(self.parse_u64()?)
197		} else {
198			None
199		};
200
201		let offset = if self.at_keyword(&Keyword::Offset) {
202			self.advance()?;
203			Some(self.parse_u64()?)
204		} else {
205			None
206		};
207
208		// Set operations: UNION [ALL] / INTERSECT / EXCEPT
209		let set_op = if self.at_keyword(&Keyword::Union) {
210			self.advance()?;
211			let op = if self.at_keyword(&Keyword::All) {
212				self.advance()?;
213				SetOp::UnionAll
214			} else {
215				SetOp::Union
216			};
217			let right = self.parse_select_statement()?;
218			Some((op, Box::new(right)))
219		} else if self.at_keyword(&Keyword::Intersect) {
220			self.advance()?;
221			let right = self.parse_select_statement()?;
222			Some((SetOp::Intersect, Box::new(right)))
223		} else if self.at_keyword(&Keyword::Except) {
224			self.advance()?;
225			let right = self.parse_select_statement()?;
226			Some((SetOp::Except, Box::new(right)))
227		} else {
228			None
229		};
230
231		Ok(SelectStatement {
232			ctes,
233			distinct,
234			columns,
235			from,
236			joins,
237			where_clause,
238			group_by,
239			having,
240			order_by,
241			limit,
242			offset,
243			set_op,
244		})
245	}
246
247	/// Parse a single FROM item (table or subquery) with optional alias.
248	/// Returns (FromClause, Option<alias>).
249	fn parse_from_item(&mut self) -> Result<(FromClause, Option<String>), Error> {
250		let from = if self.at_token(&Token::OpenParen) {
251			// Could be a subquery
252			self.advance()?;
253			if self.at_keyword(&Keyword::Select) {
254				let sel = self.parse_select_statement()?;
255				self.expect_token(Token::CloseParen)?;
256				FromClause::Subquery(Box::new(sel))
257			} else {
258				return Err(Error("expected subquery after '('".into()));
259			}
260		} else {
261			let name = self.expect_ident()?;
262			if self.at_token(&Token::Dot) {
263				self.advance()?;
264				let table = self.expect_ident()?;
265				FromClause::Table {
266					schema: Some(name),
267					name: table,
268					alias: None,
269				}
270			} else {
271				FromClause::Table {
272					name,
273					schema: None,
274					alias: None,
275				}
276			}
277		};
278
279		// Optional alias: AS alias or bare alias
280		let alias = if self.at_keyword(&Keyword::As) {
281			self.advance()?;
282			Some(self.expect_ident()?)
283		} else if !self.is_eof() && self.is_ident_like() {
284			Some(self.expect_ident()?)
285		} else {
286			None
287		};
288
289		// Embed alias into FromClause::Table if possible
290		if let Some(alias) = alias {
291			match from {
292				FromClause::Table {
293					name,
294					schema,
295					..
296				} => Ok((
297					FromClause::Table {
298						name,
299						schema,
300						alias: Some(alias),
301					},
302					None,
303				)),
304				other => Ok((other, Some(alias))),
305			}
306		} else {
307			Ok((from, None))
308		}
309	}
310
311	fn parse_cte_list(&mut self) -> Result<Vec<CteDefinition>, Error> {
312		self.expect_keyword(Keyword::With)?;
313		if self.at_keyword(&Keyword::Recursive) {
314			return Err(Error("recursive CTEs are not supported".into()));
315		}
316		let mut ctes = Vec::new();
317		loop {
318			let name = self.expect_ident()?;
319			self.expect_keyword(Keyword::As)?;
320			self.expect_token(Token::OpenParen)?;
321			let query = self.parse_select_statement()?;
322			self.expect_token(Token::CloseParen)?;
323			ctes.push(CteDefinition {
324				name,
325				query,
326			});
327			if self.at_token(&Token::Comma) {
328				self.advance()?;
329			} else {
330				break;
331			}
332		}
333		Ok(ctes)
334	}
335
336	fn parse_select_columns(&mut self) -> Result<Vec<SelectColumn>, Error> {
337		let mut cols = Vec::new();
338		loop {
339			if self.at_token(&Token::Asterisk) {
340				self.advance()?;
341				cols.push(SelectColumn::AllColumns);
342			} else if self.is_eof()
343				|| self.at_keyword(&Keyword::From)
344				|| self.at_keyword(&Keyword::Where)
345				|| self.at_keyword(&Keyword::Order)
346				|| self.at_keyword(&Keyword::Limit)
347				|| self.at_keyword(&Keyword::Group)
348				|| self.at_keyword(&Keyword::Having)
349				|| self.at_keyword(&Keyword::Union)
350				|| self.at_keyword(&Keyword::Intersect)
351				|| self.at_keyword(&Keyword::Except)
352				|| self.at_token(&Token::Semicolon)
353				|| self.at_token(&Token::CloseParen)
354			{
355				break;
356			} else {
357				let expr = self.parse_expr()?;
358				let alias = if self.at_keyword(&Keyword::As) {
359					self.advance()?;
360					Some(self.expect_ident()?)
361				} else {
362					None
363				};
364				cols.push(SelectColumn::Expr {
365					expr,
366					alias,
367				});
368			}
369
370			if self.at_token(&Token::Comma) {
371				self.advance()?;
372			} else {
373				break;
374			}
375		}
376		Ok(cols)
377	}
378
379	fn parse_from_clause(&mut self) -> Result<FromClause, Error> {
380		let (from, _alias) = self.parse_from_item()?;
381		Ok(from)
382	}
383
384	// ── JOIN ────────────────────────────────────────────────────────────
385
386	/// Check if the next tokens form a JOIN clause.  Returns true and
387	/// consumes the join-type keywords (INNER/LEFT/CROSS and JOIN) if present.
388	fn parse_join_if_present(&mut self) -> Result<bool, Error> {
389		if self.is_eof() {
390			return Ok(false);
391		}
392		// Bare JOIN
393		if self.at_keyword(&Keyword::Join) {
394			return Ok(true);
395		}
396		// INNER JOIN / LEFT JOIN / LEFT OUTER JOIN / CROSS JOIN / NATURAL JOIN / RIGHT JOIN / FULL JOIN / FULL
397		// OUTER JOIN
398		if self.at_keyword(&Keyword::Inner)
399			|| self.at_keyword(&Keyword::Left)
400			|| self.at_keyword(&Keyword::Right)
401			|| self.at_keyword(&Keyword::Cross)
402			|| self.at_keyword(&Keyword::Natural)
403			|| self.at_keyword(&Keyword::Full)
404		{
405			// Look ahead for JOIN (possibly with OUTER in between)
406			let mut look = self.pos + 1;
407			if look < self.tokens.len() && self.tokens[look] == Token::Keyword(Keyword::Outer) {
408				look += 1;
409			}
410			if look < self.tokens.len() && self.tokens[look] == Token::Keyword(Keyword::Join) {
411				return Ok(true);
412			}
413		}
414		Ok(false)
415	}
416
417	fn finish_parse_join(&mut self) -> Result<JoinClause, Error> {
418		let join_type = if self.at_keyword(&Keyword::Left) {
419			self.advance()?;
420			if self.at_keyword(&Keyword::Outer) {
421				self.advance()?;
422			}
423			self.expect_keyword(Keyword::Join)?;
424			JoinType::Left
425		} else if self.at_keyword(&Keyword::Inner) {
426			self.advance()?;
427			self.expect_keyword(Keyword::Join)?;
428			JoinType::Inner
429		} else if self.at_keyword(&Keyword::Cross) {
430			self.advance()?;
431			self.expect_keyword(Keyword::Join)?;
432			JoinType::Cross
433		} else if self.at_keyword(&Keyword::Natural) {
434			self.advance()?;
435			self.expect_keyword(Keyword::Join)?;
436			JoinType::Inner
437		} else if self.at_keyword(&Keyword::Right) {
438			self.advance()?;
439			if self.at_keyword(&Keyword::Outer) {
440				self.advance()?;
441			}
442			self.expect_keyword(Keyword::Join)?;
443			JoinType::Inner // best-effort: treat as inner
444		} else if self.at_keyword(&Keyword::Full) {
445			self.advance()?;
446			if self.at_keyword(&Keyword::Outer) {
447				self.advance()?;
448			}
449			self.expect_keyword(Keyword::Join)?;
450			JoinType::Inner // best-effort: treat as inner
451		} else {
452			self.expect_keyword(Keyword::Join)?;
453			JoinType::Inner
454		};
455
456		let table = self.parse_from_clause()?;
457		let table_alias = if self.at_keyword(&Keyword::As) {
458			self.advance()?;
459			Some(self.expect_ident()?)
460		} else if !self.is_eof() && self.is_ident_like() && !self.at_keyword(&Keyword::On) {
461			Some(self.expect_ident()?)
462		} else {
463			// Check if alias was embedded in FromClause::Table
464			match &table {
465				FromClause::Table {
466					alias,
467					..
468				} => alias.clone(),
469				_ => None,
470			}
471		};
472
473		let on = if self.at_keyword(&Keyword::On) {
474			self.advance()?;
475			self.parse_expr()?
476		} else {
477			// CROSS JOIN or NATURAL JOIN might not have ON
478			Expr::BoolLiteral(true)
479		};
480
481		Ok(JoinClause {
482			join_type,
483			table,
484			table_alias,
485			on,
486		})
487	}
488
489	// ── INSERT ──────────────────────────────────────────────────────────
490
491	fn parse_insert(&mut self) -> Result<Statement, Error> {
492		self.expect_keyword(Keyword::Insert)?;
493		self.expect_keyword(Keyword::Into)?;
494
495		let (schema, table) = self.parse_table_name()?;
496
497		let columns = if self.at_token(&Token::OpenParen) {
498			self.advance()?;
499			let cols = self.parse_ident_list()?;
500			self.expect_token(Token::CloseParen)?;
501			cols
502		} else {
503			vec![]
504		};
505
506		// INSERT INTO ... SELECT or INSERT INTO ... VALUES
507		if self.at_keyword(&Keyword::Select) || self.at_keyword(&Keyword::With) {
508			let sel = self.parse_select_statement()?;
509			return Ok(Statement::Insert(InsertStatement {
510				table,
511				schema,
512				columns,
513				source: InsertSource::Select(sel),
514			}));
515		}
516
517		self.expect_keyword(Keyword::Values)?;
518
519		let mut values = Vec::new();
520		loop {
521			self.expect_token(Token::OpenParen)?;
522			let row = self.parse_expr_list()?;
523			self.expect_token(Token::CloseParen)?;
524			values.push(row);
525			if self.at_token(&Token::Comma) {
526				self.advance()?;
527			} else {
528				break;
529			}
530		}
531
532		Ok(Statement::Insert(InsertStatement {
533			table,
534			schema,
535			columns,
536			source: InsertSource::Values(values),
537		}))
538	}
539
540	// ── UPDATE ──────────────────────────────────────────────────────────
541
542	fn parse_update(&mut self) -> Result<Statement, Error> {
543		self.expect_keyword(Keyword::Update)?;
544		let (schema, table) = self.parse_table_name()?;
545		self.expect_keyword(Keyword::Set)?;
546
547		let mut assignments = Vec::new();
548		loop {
549			let col = self.expect_ident()?;
550			self.expect_token(Token::Eq)?;
551			let val = self.parse_expr()?;
552			assignments.push((col, val));
553			if self.at_token(&Token::Comma) {
554				self.advance()?;
555			} else {
556				break;
557			}
558		}
559
560		let where_clause = if self.at_keyword(&Keyword::Where) {
561			self.advance()?;
562			Some(self.parse_expr()?)
563		} else {
564			None
565		};
566
567		Ok(Statement::Update(UpdateStatement {
568			table,
569			schema,
570			assignments,
571			where_clause,
572		}))
573	}
574
575	// ── DELETE ──────────────────────────────────────────────────────────
576
577	fn parse_delete(&mut self) -> Result<Statement, Error> {
578		self.expect_keyword(Keyword::Delete)?;
579		self.expect_keyword(Keyword::From)?;
580		let (schema, table) = self.parse_table_name()?;
581
582		let where_clause = if self.at_keyword(&Keyword::Where) {
583			self.advance()?;
584			Some(self.parse_expr()?)
585		} else {
586			None
587		};
588
589		Ok(Statement::Delete(DeleteStatement {
590			table,
591			schema,
592			where_clause,
593		}))
594	}
595
596	// ── CREATE TABLE / CREATE INDEX ────────────────────────────────────
597
598	fn parse_create(&mut self) -> Result<Statement, Error> {
599		self.expect_keyword(Keyword::Create)?;
600
601		// CREATE UNIQUE INDEX ...
602		if self.at_keyword(&Keyword::Unique) {
603			self.advance()?;
604			self.expect_keyword(Keyword::Index)?;
605			return self.parse_create_index(true);
606		}
607
608		// CREATE INDEX ...
609		if self.at_keyword(&Keyword::Index) {
610			self.advance()?;
611			return self.parse_create_index(false);
612		}
613
614		// CREATE TABLE ...
615		self.expect_keyword(Keyword::Table)?;
616
617		// IF NOT EXISTS
618		let if_not_exists = if self.at_keyword(&Keyword::If) {
619			self.advance()?;
620			self.expect_keyword(Keyword::Not)?;
621			self.expect_keyword(Keyword::Exists)?;
622			true
623		} else {
624			false
625		};
626
627		let (schema, table) = self.parse_table_name()?;
628
629		self.expect_token(Token::OpenParen)?;
630		let mut columns = Vec::new();
631		let mut primary_key = Vec::new();
632		loop {
633			if self.at_token(&Token::CloseParen) {
634				break;
635			}
636			// Check for PRIMARY KEY(...) table constraint
637			if self.at_keyword(&Keyword::Primary) {
638				self.advance()?;
639				self.expect_keyword(Keyword::Key)?;
640				self.expect_token(Token::OpenParen)?;
641				primary_key = self.parse_ident_list()?;
642				self.expect_token(Token::CloseParen)?;
643				if self.at_token(&Token::Comma) {
644					self.advance()?;
645				}
646				continue;
647			}
648			// Check for UNIQUE(...) table constraint (skip it)
649			if self.at_keyword(&Keyword::Unique) {
650				self.advance()?;
651				self.expect_token(Token::OpenParen)?;
652				let _cols = self.parse_ident_list()?;
653				self.expect_token(Token::CloseParen)?;
654				if self.at_token(&Token::Comma) {
655					self.advance()?;
656				}
657				continue;
658			}
659			let name = self.expect_ident()?;
660			let data_type = self.parse_sql_type()?;
661			let mut nullable = true;
662			if self.at_keyword(&Keyword::Not) {
663				self.advance()?;
664				self.expect_keyword(Keyword::Null)?;
665				nullable = false;
666			} else if self.at_keyword(&Keyword::Null) {
667				self.advance()?;
668				nullable = true;
669			}
670			// Column-level PRIMARY KEY
671			if self.at_keyword(&Keyword::Primary) {
672				self.advance()?;
673				self.expect_keyword(Keyword::Key)?;
674				primary_key.push(name.clone());
675				nullable = false; // PRIMARY KEY implies NOT NULL
676			}
677			// Column-level UNIQUE (skip)
678			if self.at_keyword(&Keyword::Unique) {
679				self.advance()?;
680			}
681			// DEFAULT clause (skip the expression)
682			if !self.is_eof() && matches!(self.tokens.get(self.pos), Some(Token::Keyword(Keyword::Set))) {
683				// "DEFAULT" would be an ident, not a keyword - skip
684			}
685			columns.push(ColumnDef {
686				name,
687				data_type,
688				nullable,
689			});
690			if self.at_token(&Token::Comma) {
691				self.advance()?;
692			} else {
693				break;
694			}
695		}
696		self.expect_token(Token::CloseParen)?;
697
698		Ok(Statement::CreateTable(CreateTableStatement {
699			table,
700			schema,
701			columns,
702			primary_key,
703			if_not_exists,
704		}))
705	}
706
707	fn parse_create_index(&mut self, unique: bool) -> Result<Statement, Error> {
708		// CREATE [UNIQUE] INDEX [IF NOT EXISTS] name ON table (columns...)
709		// Handle IF NOT EXISTS
710		if self.at_keyword(&Keyword::If) {
711			self.advance()?;
712			self.expect_keyword(Keyword::Not)?;
713			self.expect_keyword(Keyword::Exists)?;
714		}
715
716		let index_name = self.expect_ident()?;
717		self.expect_keyword(Keyword::On)?;
718		let (schema, table) = self.parse_table_name()?;
719
720		self.expect_token(Token::OpenParen)?;
721		let mut columns = Vec::new();
722		loop {
723			let name = self.expect_ident()?;
724			let direction = if self.at_keyword(&Keyword::Asc) {
725				self.advance()?;
726				Some(OrderDirection::Asc)
727			} else if self.at_keyword(&Keyword::Desc) {
728				self.advance()?;
729				Some(OrderDirection::Desc)
730			} else {
731				None
732			};
733			columns.push(IndexColumn {
734				name,
735				direction,
736			});
737			if self.at_token(&Token::Comma) {
738				self.advance()?;
739			} else {
740				break;
741			}
742		}
743		self.expect_token(Token::CloseParen)?;
744
745		// Skip optional WHERE clause for partial indexes
746		if self.at_keyword(&Keyword::Where) {
747			self.advance()?;
748			let _ = self.parse_expr()?;
749		}
750
751		Ok(Statement::CreateIndex(CreateIndexStatement {
752			unique,
753			index_name,
754			table,
755			schema,
756			columns,
757		}))
758	}
759
760	// ── DROP TABLE ─────────────────────────────────────────────────────
761
762	fn parse_drop(&mut self) -> Result<Statement, Error> {
763		self.expect_keyword(Keyword::Drop)?;
764
765		// DROP INDEX (skip entirely)
766		if self.at_keyword(&Keyword::Index) {
767			self.advance()?;
768			// IF EXISTS
769			let _if_exists = if self.at_keyword(&Keyword::If) {
770				self.advance()?;
771				self.expect_keyword(Keyword::Exists)?;
772				true
773			} else {
774				false
775			};
776			let index_name = self.expect_ident()?;
777			// DROP INDEX just emits as-is
778			return Ok(Statement::DropTable(DropTableStatement {
779				table: index_name,
780				schema: None,
781				if_exists: _if_exists,
782			}));
783		}
784
785		self.expect_keyword(Keyword::Table)?;
786
787		let if_exists = if self.at_keyword(&Keyword::If) {
788			self.advance()?;
789			self.expect_keyword(Keyword::Exists)?;
790			true
791		} else {
792			false
793		};
794
795		let (schema, table) = self.parse_table_name()?;
796
797		Ok(Statement::DropTable(DropTableStatement {
798			table,
799			schema,
800			if_exists,
801		}))
802	}
803
804	// ── Type parsing ────────────────────────────────────────────────────
805
806	fn parse_sql_type(&mut self) -> Result<SqlType, Error> {
807		let tok = self.advance()?;
808		match tok {
809			Token::Keyword(Keyword::Int) => Ok(SqlType::Int),
810			Token::Keyword(Keyword::Int2) => Ok(SqlType::Int2),
811			Token::Keyword(Keyword::Int4) => Ok(SqlType::Int4),
812			Token::Keyword(Keyword::Int8) => Ok(SqlType::Int8),
813			Token::Keyword(Keyword::Smallint) => Ok(SqlType::Smallint),
814			Token::Keyword(Keyword::Integer) => Ok(SqlType::Integer),
815			Token::Keyword(Keyword::Bigint) => Ok(SqlType::Bigint),
816			Token::Keyword(Keyword::Float4) => Ok(SqlType::Float4),
817			Token::Keyword(Keyword::Float8) => Ok(SqlType::Float8),
818			Token::Keyword(Keyword::FloatKw) => Ok(SqlType::FloatType),
819			Token::Keyword(Keyword::Numeric) => Ok(SqlType::Numeric),
820			Token::Keyword(Keyword::Real) => Ok(SqlType::Real),
821			Token::Keyword(Keyword::Double) => {
822				// DOUBLE PRECISION
823				if self.at_keyword(&Keyword::Precision) {
824					self.advance()?;
825				}
826				Ok(SqlType::Double)
827			}
828			Token::Keyword(Keyword::Boolean) => Ok(SqlType::Boolean),
829			Token::Keyword(Keyword::Bool) => Ok(SqlType::Bool),
830			Token::Keyword(Keyword::Text) => Ok(SqlType::Text),
831			Token::Keyword(Keyword::Utf8) => Ok(SqlType::Utf8),
832			Token::Keyword(Keyword::Blob) => Ok(SqlType::Blob),
833			Token::Keyword(Keyword::Varchar) => {
834				let len = if self.at_token(&Token::OpenParen) {
835					self.advance()?;
836					let n = self.parse_u64()?;
837					self.expect_token(Token::CloseParen)?;
838					Some(n)
839				} else {
840					None
841				};
842				Ok(SqlType::Varchar(len))
843			}
844			Token::Keyword(Keyword::Char) => {
845				let len = if self.at_token(&Token::OpenParen) {
846					self.advance()?;
847					let n = self.parse_u64()?;
848					self.expect_token(Token::CloseParen)?;
849					Some(n)
850				} else {
851					None
852				};
853				Ok(SqlType::Char(len))
854			}
855			_ => Err(Error(format!("expected SQL type, got {tok:?}"))),
856		}
857	}
858
859	// ── Expression parsing (Pratt-style precedence) ─────────────────────
860
861	fn parse_expr(&mut self) -> Result<Expr, Error> {
862		self.parse_or()
863	}
864
865	fn parse_or(&mut self) -> Result<Expr, Error> {
866		let mut left = self.parse_and()?;
867		while self.at_keyword(&Keyword::Or) {
868			self.advance()?;
869			let right = self.parse_and()?;
870			left = Expr::BinaryOp {
871				left: Box::new(left),
872				op: BinaryOp::Or,
873				right: Box::new(right),
874			};
875		}
876		Ok(left)
877	}
878
879	fn parse_and(&mut self) -> Result<Expr, Error> {
880		let mut left = self.parse_not()?;
881		while self.at_keyword(&Keyword::And) {
882			self.advance()?;
883			let right = self.parse_not()?;
884			left = Expr::BinaryOp {
885				left: Box::new(left),
886				op: BinaryOp::And,
887				right: Box::new(right),
888			};
889		}
890		Ok(left)
891	}
892
893	fn parse_not(&mut self) -> Result<Expr, Error> {
894		if self.at_keyword(&Keyword::Not) {
895			// Check for NOT EXISTS
896			if matches!(self.tokens.get(self.pos + 1), Some(Token::Keyword(Keyword::Exists))) {
897				self.advance()?; // NOT
898				self.advance()?; // EXISTS
899				self.expect_token(Token::OpenParen)?;
900				let sel = self.parse_select_statement()?;
901				self.expect_token(Token::CloseParen)?;
902				return Ok(Expr::UnaryOp {
903					op: UnaryOp::Not,
904					expr: Box::new(Expr::Exists(Box::new(sel))),
905				});
906			}
907			self.advance()?;
908			let expr = self.parse_not()?;
909			Ok(Expr::UnaryOp {
910				op: UnaryOp::Not,
911				expr: Box::new(expr),
912			})
913		} else {
914			self.parse_comparison()
915		}
916	}
917
918	fn parse_comparison(&mut self) -> Result<Expr, Error> {
919		let mut left = self.parse_addition()?;
920
921		// IS NULL / IS NOT NULL
922		if self.at_keyword(&Keyword::Is) {
923			self.advance()?;
924			if self.at_keyword(&Keyword::Not) {
925				self.advance()?;
926				self.expect_keyword(Keyword::Null)?;
927				return Ok(Expr::IsNull {
928					expr: Box::new(left),
929					negated: true,
930				});
931			} else {
932				self.expect_keyword(Keyword::Null)?;
933				return Ok(Expr::IsNull {
934					expr: Box::new(left),
935					negated: false,
936				});
937			}
938		}
939
940		// NOT BETWEEN / BETWEEN ... AND ...
941		if self.at_keyword(&Keyword::Not)
942			&& matches!(self.tokens.get(self.pos + 1), Some(Token::Keyword(Keyword::Between)))
943		{
944			self.advance()?; // NOT
945			self.advance()?; // BETWEEN
946			let low = self.parse_addition()?;
947			self.expect_keyword(Keyword::And)?;
948			let high = self.parse_addition()?;
949			return Ok(Expr::Between {
950				expr: Box::new(left),
951				low: Box::new(low),
952				high: Box::new(high),
953				negated: true,
954			});
955		}
956
957		if self.at_keyword(&Keyword::Between) {
958			self.advance()?;
959			let low = self.parse_addition()?;
960			self.expect_keyword(Keyword::And)?;
961			let high = self.parse_addition()?;
962			return Ok(Expr::Between {
963				expr: Box::new(left),
964				low: Box::new(low),
965				high: Box::new(high),
966				negated: false,
967			});
968		}
969
970		// NOT LIKE / LIKE
971		if self.at_keyword(&Keyword::Not)
972			&& matches!(self.tokens.get(self.pos + 1), Some(Token::Keyword(Keyword::Like)))
973		{
974			self.advance()?; // NOT
975			self.advance()?; // LIKE
976			let pattern = self.parse_addition()?;
977			return Ok(Expr::Like {
978				expr: Box::new(left),
979				pattern: Box::new(pattern),
980				negated: true,
981			});
982		}
983
984		if self.at_keyword(&Keyword::Like) {
985			self.advance()?;
986			let pattern = self.parse_addition()?;
987			return Ok(Expr::Like {
988				expr: Box::new(left),
989				pattern: Box::new(pattern),
990				negated: false,
991			});
992		}
993
994		// NOT GLOB / GLOB (treat like LIKE for now)
995		if self.at_keyword(&Keyword::Not)
996			&& matches!(self.tokens.get(self.pos + 1), Some(Token::Keyword(Keyword::Glob)))
997		{
998			self.advance()?; // NOT
999			self.advance()?; // GLOB
1000			let pattern = self.parse_addition()?;
1001			return Ok(Expr::Like {
1002				expr: Box::new(left),
1003				pattern: Box::new(pattern),
1004				negated: true,
1005			});
1006		}
1007
1008		if self.at_keyword(&Keyword::Glob) {
1009			self.advance()?;
1010			let pattern = self.parse_addition()?;
1011			return Ok(Expr::Like {
1012				expr: Box::new(left),
1013				pattern: Box::new(pattern),
1014				negated: false,
1015			});
1016		}
1017
1018		// NOT IN / IN (...)
1019		if self.at_keyword(&Keyword::Not)
1020			&& matches!(self.tokens.get(self.pos + 1), Some(Token::Keyword(Keyword::In)))
1021		{
1022			self.advance()?; // NOT
1023			self.advance()?; // IN
1024			self.expect_token(Token::OpenParen)?;
1025			// Check for subquery
1026			if self.at_keyword(&Keyword::Select) || self.at_keyword(&Keyword::With) {
1027				let sel = self.parse_select_statement()?;
1028				self.expect_token(Token::CloseParen)?;
1029				return Ok(Expr::InSelect {
1030					expr: Box::new(left),
1031					subquery: Box::new(sel),
1032					negated: true,
1033				});
1034			}
1035			let list = self.parse_expr_list()?;
1036			self.expect_token(Token::CloseParen)?;
1037			return Ok(Expr::InList {
1038				expr: Box::new(left),
1039				list,
1040				negated: true,
1041			});
1042		}
1043
1044		if self.at_keyword(&Keyword::In) {
1045			self.advance()?;
1046			self.expect_token(Token::OpenParen)?;
1047			// Check for subquery
1048			if self.at_keyword(&Keyword::Select) || self.at_keyword(&Keyword::With) {
1049				let sel = self.parse_select_statement()?;
1050				self.expect_token(Token::CloseParen)?;
1051				return Ok(Expr::InSelect {
1052					expr: Box::new(left),
1053					subquery: Box::new(sel),
1054					negated: false,
1055				});
1056			}
1057			let list = self.parse_expr_list()?;
1058			self.expect_token(Token::CloseParen)?;
1059			return Ok(Expr::InList {
1060				expr: Box::new(left),
1061				list,
1062				negated: false,
1063			});
1064		}
1065
1066		// Comparison operators
1067		let op = match self.tokens.get(self.pos) {
1068			Some(Token::Eq) => Some(BinaryOp::Eq),
1069			Some(Token::NotEq) => Some(BinaryOp::NotEq),
1070			Some(Token::Lt) => Some(BinaryOp::Lt),
1071			Some(Token::Gt) => Some(BinaryOp::Gt),
1072			Some(Token::LtEq) => Some(BinaryOp::LtEq),
1073			Some(Token::GtEq) => Some(BinaryOp::GtEq),
1074			_ => None,
1075		};
1076		if let Some(op) = op {
1077			self.advance()?;
1078			let right = self.parse_addition()?;
1079			left = Expr::BinaryOp {
1080				left: Box::new(left),
1081				op,
1082				right: Box::new(right),
1083			};
1084		}
1085
1086		Ok(left)
1087	}
1088
1089	fn parse_addition(&mut self) -> Result<Expr, Error> {
1090		let mut left = self.parse_multiplication()?;
1091		loop {
1092			let op = match self.tokens.get(self.pos) {
1093				Some(Token::Plus) => Some(BinaryOp::Add),
1094				Some(Token::Minus) => Some(BinaryOp::Sub),
1095				Some(Token::Concat) => Some(BinaryOp::Concat),
1096				_ => None,
1097			};
1098			if let Some(op) = op {
1099				self.advance()?;
1100				let right = self.parse_multiplication()?;
1101				left = Expr::BinaryOp {
1102					left: Box::new(left),
1103					op,
1104					right: Box::new(right),
1105				};
1106			} else {
1107				break;
1108			}
1109		}
1110		Ok(left)
1111	}
1112
1113	fn parse_multiplication(&mut self) -> Result<Expr, Error> {
1114		let mut left = self.parse_unary()?;
1115		loop {
1116			let op = match self.tokens.get(self.pos) {
1117				Some(Token::Asterisk) => Some(BinaryOp::Mul),
1118				Some(Token::Slash) => Some(BinaryOp::Div),
1119				Some(Token::Percent) => Some(BinaryOp::Mod),
1120				_ => None,
1121			};
1122			if let Some(op) = op {
1123				self.advance()?;
1124				let right = self.parse_unary()?;
1125				left = Expr::BinaryOp {
1126					left: Box::new(left),
1127					op,
1128					right: Box::new(right),
1129				};
1130			} else {
1131				break;
1132			}
1133		}
1134		Ok(left)
1135	}
1136
1137	fn parse_unary(&mut self) -> Result<Expr, Error> {
1138		if self.at_token(&Token::Minus) {
1139			self.advance()?;
1140			let expr = self.parse_unary()?;
1141			return Ok(Expr::UnaryOp {
1142				op: UnaryOp::Neg,
1143				expr: Box::new(expr),
1144			});
1145		}
1146		// Unary + (identity)
1147		if self.at_token(&Token::Plus) {
1148			self.advance()?;
1149			return self.parse_unary();
1150		}
1151		self.parse_primary()
1152	}
1153
1154	fn parse_primary(&mut self) -> Result<Expr, Error> {
1155		let tok = self.peek()?.clone();
1156		match tok {
1157			Token::Integer(n) => {
1158				self.advance()?;
1159				Ok(Expr::IntegerLiteral(n))
1160			}
1161			Token::Float(f) => {
1162				self.advance()?;
1163				Ok(Expr::FloatLiteral(f))
1164			}
1165			Token::StringLit(s) => {
1166				self.advance()?;
1167				Ok(Expr::StringLiteral(s))
1168			}
1169			Token::Keyword(Keyword::True) => {
1170				self.advance()?;
1171				Ok(Expr::BoolLiteral(true))
1172			}
1173			Token::Keyword(Keyword::False) => {
1174				self.advance()?;
1175				Ok(Expr::BoolLiteral(false))
1176			}
1177			Token::Keyword(Keyword::Null) => {
1178				self.advance()?;
1179				Ok(Expr::Null)
1180			}
1181			Token::Keyword(Keyword::Cast) => self.parse_cast_expr(),
1182			Token::Keyword(Keyword::Case) => self.parse_case_expr(),
1183			Token::Keyword(Keyword::Exists) => {
1184				self.advance()?;
1185				self.expect_token(Token::OpenParen)?;
1186				let sel = self.parse_select_statement()?;
1187				self.expect_token(Token::CloseParen)?;
1188				Ok(Expr::Exists(Box::new(sel)))
1189			}
1190			Token::Keyword(Keyword::Not) => {
1191				// NOT EXISTS handled at parse_not level, but if we get here via parse_primary...
1192				if matches!(self.tokens.get(self.pos + 1), Some(Token::Keyword(Keyword::Exists))) {
1193					self.advance()?; // NOT
1194					self.advance()?; // EXISTS
1195					self.expect_token(Token::OpenParen)?;
1196					let sel = self.parse_select_statement()?;
1197					self.expect_token(Token::CloseParen)?;
1198					Ok(Expr::UnaryOp {
1199						op: UnaryOp::Not,
1200						expr: Box::new(Expr::Exists(Box::new(sel))),
1201					})
1202				} else {
1203					Err(Error(format!("unexpected token in expression: {tok:?}")))
1204				}
1205			}
1206			// Aggregate function keywords
1207			Token::Keyword(Keyword::Count)
1208			| Token::Keyword(Keyword::Sum)
1209			| Token::Keyword(Keyword::Avg)
1210			| Token::Keyword(Keyword::Min)
1211			| Token::Keyword(Keyword::Max) => {
1212				let name = keyword_to_string(match &self.advance()? {
1213					Token::Keyword(kw) => kw,
1214					_ => unreachable!(),
1215				});
1216				self.expect_token(Token::OpenParen)?;
1217				// Handle DISTINCT inside aggregate: COUNT(DISTINCT x)
1218				let distinct_prefix = if self.at_keyword(&Keyword::Distinct) {
1219					self.advance()?;
1220					true
1221				} else {
1222					false
1223				};
1224				let args = if self.at_token(&Token::Asterisk) {
1225					self.advance()?;
1226					vec![Expr::Identifier("*".into())]
1227				} else {
1228					self.parse_expr_list()?
1229				};
1230				self.expect_token(Token::CloseParen)?;
1231				if distinct_prefix {
1232					// Wrap as DISTINCT_name function
1233					Ok(Expr::FunctionCall {
1234						name: format!("{name}_DISTINCT"),
1235						args,
1236					})
1237				} else {
1238					Ok(Expr::FunctionCall {
1239						name,
1240						args,
1241					})
1242				}
1243			}
1244			Token::OpenParen => {
1245				self.advance()?;
1246				// Check for subquery
1247				if self.at_keyword(&Keyword::Select) || self.at_keyword(&Keyword::With) {
1248					let sel = self.parse_select_statement()?;
1249					self.expect_token(Token::CloseParen)?;
1250					return Ok(Expr::Subquery(Box::new(sel)));
1251				}
1252				let expr = self.parse_expr()?;
1253				self.expect_token(Token::CloseParen)?;
1254				Ok(Expr::Nested(Box::new(expr)))
1255			}
1256			Token::Ident(_) => {
1257				let name = self.expect_ident()?;
1258				// Check for qualified identifier (table.column)
1259				if self.at_token(&Token::Dot) {
1260					self.advance()?;
1261					let col = self.expect_ident()?;
1262					// Check for function call on qualified name
1263					if self.at_token(&Token::OpenParen) {
1264						self.advance()?;
1265						let args = if self.at_token(&Token::CloseParen) {
1266							vec![]
1267						} else if self.at_token(&Token::Asterisk) {
1268							self.advance()?;
1269							vec![Expr::Identifier("*".into())]
1270						} else {
1271							self.parse_expr_list()?
1272						};
1273						self.expect_token(Token::CloseParen)?;
1274						Ok(Expr::FunctionCall {
1275							name: format!("{name}.{col}"),
1276							args,
1277						})
1278					} else {
1279						Ok(Expr::QualifiedIdentifier(name, col))
1280					}
1281				}
1282				// Check for function call
1283				else if self.at_token(&Token::OpenParen) {
1284					self.advance()?;
1285					let args = if self.at_token(&Token::CloseParen) {
1286						vec![]
1287					} else if self.at_token(&Token::Asterisk) {
1288						self.advance()?;
1289						vec![Expr::Identifier("*".into())]
1290					} else {
1291						self.parse_expr_list()?
1292					};
1293					self.expect_token(Token::CloseParen)?;
1294					Ok(Expr::FunctionCall {
1295						name,
1296						args,
1297					})
1298				} else {
1299					Ok(Expr::Identifier(name))
1300				}
1301			}
1302			_ => Err(Error(format!("unexpected token in expression: {tok:?}"))),
1303		}
1304	}
1305
1306	fn parse_cast_expr(&mut self) -> Result<Expr, Error> {
1307		self.expect_keyword(Keyword::Cast)?;
1308		self.expect_token(Token::OpenParen)?;
1309		let expr = self.parse_expr()?;
1310		self.expect_keyword(Keyword::As)?;
1311		let data_type = self.parse_sql_type()?;
1312		self.expect_token(Token::CloseParen)?;
1313		Ok(Expr::Cast {
1314			expr: Box::new(expr),
1315			data_type,
1316		})
1317	}
1318
1319	fn parse_case_expr(&mut self) -> Result<Expr, Error> {
1320		self.expect_keyword(Keyword::Case)?;
1321
1322		// Simple CASE (CASE expr WHEN ...) vs Searched CASE (CASE WHEN ...)
1323		let operand = if !self.at_keyword(&Keyword::When) {
1324			Some(Box::new(self.parse_expr()?))
1325		} else {
1326			None
1327		};
1328
1329		let mut when_clauses = Vec::new();
1330		while self.at_keyword(&Keyword::When) {
1331			self.advance()?;
1332			let condition = self.parse_expr()?;
1333			self.expect_keyword(Keyword::Then)?;
1334			let result = self.parse_expr()?;
1335			when_clauses.push((condition, result));
1336		}
1337
1338		let else_clause = if self.at_keyword(&Keyword::Else) {
1339			self.advance()?;
1340			Some(Box::new(self.parse_expr()?))
1341		} else {
1342			None
1343		};
1344
1345		self.expect_keyword(Keyword::End)?;
1346
1347		Ok(Expr::Case {
1348			operand,
1349			when_clauses,
1350			else_clause,
1351		})
1352	}
1353
1354	// ── Utility ─────────────────────────────────────────────────────────
1355
1356	fn parse_expr_list(&mut self) -> Result<Vec<Expr>, Error> {
1357		let mut exprs = Vec::new();
1358		exprs.push(self.parse_expr()?);
1359		while self.at_token(&Token::Comma) {
1360			self.advance()?;
1361			exprs.push(self.parse_expr()?);
1362		}
1363		Ok(exprs)
1364	}
1365
1366	fn parse_ident_list(&mut self) -> Result<Vec<String>, Error> {
1367		let mut names = Vec::new();
1368		names.push(self.expect_ident()?);
1369		while self.at_token(&Token::Comma) {
1370			self.advance()?;
1371			names.push(self.expect_ident()?);
1372		}
1373		Ok(names)
1374	}
1375
1376	fn parse_order_by_list(&mut self) -> Result<Vec<OrderByItem>, Error> {
1377		let mut items = Vec::new();
1378		loop {
1379			let expr = self.parse_expr()?;
1380			let direction = if self.at_keyword(&Keyword::Desc) {
1381				self.advance()?;
1382				OrderDirection::Desc
1383			} else {
1384				if self.at_keyword(&Keyword::Asc) {
1385					self.advance()?;
1386				}
1387				OrderDirection::Asc
1388			};
1389			items.push(OrderByItem {
1390				expr,
1391				direction,
1392			});
1393			if self.at_token(&Token::Comma) {
1394				self.advance()?;
1395			} else {
1396				break;
1397			}
1398		}
1399		Ok(items)
1400	}
1401
1402	fn parse_u64(&mut self) -> Result<u64, Error> {
1403		let tok = self.advance()?;
1404		match tok {
1405			Token::Integer(n) if n >= 0 => Ok(n as u64),
1406			_ => Err(Error(format!("expected positive integer, got {tok:?}"))),
1407		}
1408	}
1409
1410	fn parse_table_name(&mut self) -> Result<(Option<String>, String), Error> {
1411		let name = self.expect_ident()?;
1412		if self.at_token(&Token::Dot) {
1413			self.advance()?;
1414			let table = self.expect_ident()?;
1415			Ok((Some(name), table))
1416		} else {
1417			Ok((None, name))
1418		}
1419	}
1420}
1421
1422/// Keywords that are structural (end a FROM/SELECT clause, etc.)
1423/// and should NOT be treated as bare aliases.
1424fn is_structural_keyword(kw: &Keyword) -> bool {
1425	matches!(
1426		kw,
1427		Keyword::Where
1428			| Keyword::Order | Keyword::Group
1429			| Keyword::Having | Keyword::Limit
1430			| Keyword::Offset | Keyword::Join
1431			| Keyword::Inner | Keyword::Left
1432			| Keyword::Right | Keyword::Cross
1433			| Keyword::Outer | Keyword::Full
1434			| Keyword::Natural | Keyword::On
1435			| Keyword::Set | Keyword::Values
1436			| Keyword::Select | Keyword::From
1437			| Keyword::Union | Keyword::Intersect
1438			| Keyword::Except | Keyword::When
1439			| Keyword::Then | Keyword::Else
1440			| Keyword::End | Keyword::And
1441			| Keyword::Or | Keyword::Not
1442	)
1443}
1444
1445fn keyword_to_string(kw: &Keyword) -> String {
1446	match kw {
1447		Keyword::Select => "SELECT",
1448		Keyword::From => "FROM",
1449		Keyword::Where => "WHERE",
1450		Keyword::And => "AND",
1451		Keyword::Or => "OR",
1452		Keyword::Not => "NOT",
1453		Keyword::As => "AS",
1454		Keyword::Order => "ORDER",
1455		Keyword::By => "BY",
1456		Keyword::Asc => "ASC",
1457		Keyword::Desc => "DESC",
1458		Keyword::Limit => "LIMIT",
1459		Keyword::Offset => "OFFSET",
1460		Keyword::Group => "GROUP",
1461		Keyword::Having => "HAVING",
1462		Keyword::Distinct => "DISTINCT",
1463		Keyword::Insert => "INSERT",
1464		Keyword::Into => "INTO",
1465		Keyword::Values => "VALUES",
1466		Keyword::Update => "UPDATE",
1467		Keyword::Set => "SET",
1468		Keyword::Delete => "DELETE",
1469		Keyword::Create => "CREATE",
1470		Keyword::Table => "TABLE",
1471		Keyword::Join => "JOIN",
1472		Keyword::Inner => "INNER",
1473		Keyword::Left => "LEFT",
1474		Keyword::Right => "RIGHT",
1475		Keyword::On => "ON",
1476		Keyword::Null => "NULL",
1477		Keyword::True => "true",
1478		Keyword::False => "false",
1479		Keyword::Is => "IS",
1480		Keyword::In => "IN",
1481		Keyword::Between => "BETWEEN",
1482		Keyword::Cast => "CAST",
1483		Keyword::Count => "COUNT",
1484		Keyword::Sum => "SUM",
1485		Keyword::Avg => "AVG",
1486		Keyword::Min => "MIN",
1487		Keyword::Max => "MAX",
1488		Keyword::Int => "INT",
1489		Keyword::Int2 => "INT2",
1490		Keyword::Int4 => "INT4",
1491		Keyword::Int8 => "INT8",
1492		Keyword::Smallint => "SMALLINT",
1493		Keyword::Integer => "INTEGER",
1494		Keyword::Bigint => "BIGINT",
1495		Keyword::Float4 => "FLOAT4",
1496		Keyword::Float8 => "FLOAT8",
1497		Keyword::Real => "REAL",
1498		Keyword::Double => "DOUBLE",
1499		Keyword::Precision => "PRECISION",
1500		Keyword::Boolean => "BOOLEAN",
1501		Keyword::Bool => "BOOL",
1502		Keyword::Varchar => "VARCHAR",
1503		Keyword::Text => "TEXT",
1504		Keyword::Char => "CHAR",
1505		Keyword::Utf8 => "UTF8",
1506		Keyword::Blob => "BLOB",
1507		Keyword::Primary => "PRIMARY",
1508		Keyword::Key => "KEY",
1509		Keyword::With => "WITH",
1510		Keyword::Recursive => "RECURSIVE",
1511		Keyword::Case => "CASE",
1512		Keyword::When => "WHEN",
1513		Keyword::Then => "THEN",
1514		Keyword::Else => "ELSE",
1515		Keyword::End => "END",
1516		Keyword::Exists => "EXISTS",
1517		Keyword::Union => "UNION",
1518		Keyword::All => "ALL",
1519		Keyword::Intersect => "INTERSECT",
1520		Keyword::Except => "EXCEPT",
1521		Keyword::Like => "LIKE",
1522		Keyword::Glob => "GLOB",
1523		Keyword::If => "IF",
1524		Keyword::FloatKw => "FLOAT",
1525		Keyword::Index => "INDEX",
1526		Keyword::Unique => "UNIQUE",
1527		Keyword::Drop => "DROP",
1528		Keyword::Cross => "CROSS",
1529		Keyword::Outer => "OUTER",
1530		Keyword::Full => "FULL",
1531		Keyword::Natural => "NATURAL",
1532		Keyword::Numeric => "NUMERIC",
1533	}
1534	.into()
1535}
1536
1537#[cfg(test)]
1538mod tests {
1539	use super::*;
1540	use crate::token::tokenize;
1541
1542	#[test]
1543	fn test_parse_simple_select() {
1544		let tokens = tokenize("SELECT id, name FROM users").unwrap();
1545		let stmt = Parser::new(tokens).parse().unwrap();
1546		match stmt {
1547			Statement::Select(sel) => {
1548				assert_eq!(sel.columns.len(), 2);
1549				assert!(sel.from.is_some());
1550			}
1551			_ => panic!("expected select"),
1552		}
1553	}
1554
1555	#[test]
1556	fn test_parse_select_star() {
1557		let tokens = tokenize("SELECT * FROM users").unwrap();
1558		let stmt = Parser::new(tokens).parse().unwrap();
1559		match stmt {
1560			Statement::Select(sel) => {
1561				assert!(matches!(sel.columns[0], SelectColumn::AllColumns));
1562			}
1563			_ => panic!("expected select"),
1564		}
1565	}
1566
1567	#[test]
1568	fn test_parse_where() {
1569		let tokens = tokenize("SELECT * FROM users WHERE age > 18").unwrap();
1570		let stmt = Parser::new(tokens).parse().unwrap();
1571		match stmt {
1572			Statement::Select(sel) => {
1573				assert!(sel.where_clause.is_some());
1574			}
1575			_ => panic!("expected select"),
1576		}
1577	}
1578
1579	#[test]
1580	fn test_parse_insert() {
1581		let tokens = tokenize("INSERT INTO users (id, name) VALUES (1, 'Alice')").unwrap();
1582		let stmt = Parser::new(tokens).parse().unwrap();
1583		match stmt {
1584			Statement::Insert(ins) => {
1585				assert_eq!(ins.table, "users");
1586				assert_eq!(ins.columns.len(), 2);
1587				match &ins.source {
1588					InsertSource::Values(v) => assert_eq!(v.len(), 1),
1589					_ => panic!("expected values"),
1590				}
1591			}
1592			_ => panic!("expected insert"),
1593		}
1594	}
1595}