1mod ddl;
27mod delete;
28mod expression;
29mod insert;
30mod select;
31mod update;
32
33use bumpalo::Bump;
34use vibesql_ast::arena::{
35 AlterTableStmt, ArenaInterner, Converter, DeleteStmt, Expression, InsertStmt, SelectStmt,
36 Statement, Symbol, UpdateStmt,
37};
38
39use crate::keywords::Keyword;
40use crate::{Lexer, ParseError, Token};
41
42pub struct ArenaParser<'arena> {
50 tokens: Vec<Token>,
51 position: usize,
52 placeholder_count: usize,
53 arena: &'arena Bump,
54 interner: ArenaInterner<'arena>,
55}
56
57impl<'arena> ArenaParser<'arena> {
58 pub fn new(tokens: Vec<Token>, arena: &'arena Bump) -> Self {
60 ArenaParser {
61 tokens,
62 position: 0,
63 placeholder_count: 0,
64 arena,
65 interner: ArenaInterner::new(arena),
66 }
67 }
68
69 pub fn interner(&self) -> &ArenaInterner<'arena> {
71 &self.interner
72 }
73
74 pub fn into_interner(self) -> ArenaInterner<'arena> {
76 self.interner
77 }
78
79 pub fn parse_sql(
84 input: &str,
85 arena: &'arena Bump,
86 ) -> Result<Statement<'arena>, ParseError> {
87 let mut lexer = Lexer::new(input);
88 let tokens = lexer
89 .tokenize()
90 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
91
92 let mut parser = ArenaParser::new(tokens, arena);
93 parser.parse_statement()
94 }
95
96 pub fn parse_select(
100 input: &str,
101 arena: &'arena Bump,
102 ) -> Result<&'arena SelectStmt<'arena>, ParseError> {
103 let mut lexer = Lexer::new(input);
104 let tokens = lexer
105 .tokenize()
106 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
107
108 let mut parser = ArenaParser::new(tokens, arena);
109 parser.parse_select_statement()
110 }
111
112 pub fn parse_select_with_interner(
116 input: &str,
117 arena: &'arena Bump,
118 ) -> Result<(&'arena SelectStmt<'arena>, ArenaInterner<'arena>), ParseError> {
119 let mut lexer = Lexer::new(input);
120 let tokens = lexer
121 .tokenize()
122 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
123
124 let mut parser = ArenaParser::new(tokens, arena);
125 let stmt = parser.parse_select_statement()?;
126 Ok((stmt, parser.into_interner()))
127 }
128
129 fn parse_statement(&mut self) -> Result<Statement<'arena>, ParseError> {
131 while self.try_consume(&Token::Semicolon) {}
133
134 match self.peek() {
135 Token::Keyword(Keyword::Select) | Token::Keyword(Keyword::With) => {
137 let stmt = self.parse_select_statement()?;
138 Ok(Statement::Select(stmt))
139 }
140 Token::Keyword(Keyword::Insert) => {
141 let stmt = self.parse_insert_statement()?;
142 Ok(Statement::Insert(stmt.clone()))
143 }
144 Token::Keyword(Keyword::Replace) => {
145 let stmt = self.parse_replace_statement()?;
146 Ok(Statement::Insert(stmt.clone()))
147 }
148 Token::Keyword(Keyword::Update) => {
149 let stmt = self.parse_update_statement()?;
150 Ok(Statement::Update(stmt.clone()))
151 }
152 Token::Keyword(Keyword::Delete) => {
153 let stmt = self.parse_delete_statement()?;
154 Ok(Statement::Delete(stmt.clone()))
155 }
156
157 Token::Keyword(Keyword::Create) => self.parse_create_statement(),
159 Token::Keyword(Keyword::Drop) => self.parse_drop_statement(),
160 Token::Keyword(Keyword::Alter) => {
161 let stmt = self.parse_alter_table_statement()?;
162 Ok(Statement::AlterTable(stmt.clone()))
163 }
164 Token::Keyword(Keyword::Truncate) => {
165 let stmt = self.parse_truncate_table_statement()?;
166 Ok(Statement::TruncateTable(stmt))
167 }
168 Token::Keyword(Keyword::Analyze) => {
169 let stmt = self.parse_analyze_statement()?;
170 Ok(Statement::Analyze(stmt))
171 }
172
173 Token::Keyword(Keyword::Begin) | Token::Keyword(Keyword::Start) => {
175 let stmt = self.parse_begin_statement()?;
176 Ok(Statement::BeginTransaction(stmt))
177 }
178 Token::Keyword(Keyword::Commit) => {
179 let stmt = self.parse_commit_statement()?;
180 Ok(Statement::Commit(stmt))
181 }
182 Token::Keyword(Keyword::Rollback) => {
183 if self.peek_next_keyword(Keyword::To) {
185 let stmt = self.parse_rollback_to_savepoint_statement()?;
186 Ok(Statement::RollbackToSavepoint(stmt))
187 } else {
188 let stmt = self.parse_rollback_statement()?;
189 Ok(Statement::Rollback(stmt))
190 }
191 }
192 Token::Keyword(Keyword::Savepoint) => {
193 let stmt = self.parse_savepoint_statement()?;
194 Ok(Statement::Savepoint(stmt))
195 }
196 Token::Keyword(Keyword::Release) => {
197 let stmt = self.parse_release_savepoint_statement()?;
198 Ok(Statement::ReleaseSavepoint(stmt))
199 }
200
201 _ => Err(ParseError {
202 message: format!("Unexpected token: {:?}", self.peek()),
203 }),
204 }
205 }
206
207 fn parse_create_statement(&mut self) -> Result<Statement<'arena>, ParseError> {
209 let mut offset = 1; if matches!(self.peek_at_offset(offset), Token::Keyword(Keyword::Or)) {
214 offset += 2; }
216
217 if matches!(
219 self.peek_at_offset(offset),
220 Token::Keyword(Keyword::Unique)
221 | Token::Keyword(Keyword::Fulltext)
222 | Token::Keyword(Keyword::Spatial)
223 ) {
224 offset += 1;
225 }
226
227 if matches!(
229 self.peek_at_offset(offset),
230 Token::Keyword(Keyword::Temp) | Token::Keyword(Keyword::Temporary)
231 ) {
232 offset += 1;
233 }
234
235 match self.peek_at_offset(offset) {
236 Token::Keyword(Keyword::Index) => {
237 let stmt = self.parse_create_index_statement()?;
238 Ok(Statement::CreateIndex(stmt))
239 }
240 Token::Keyword(Keyword::View) => {
241 let stmt = self.parse_create_view_statement()?;
242 Ok(Statement::CreateView(stmt))
243 }
244 _ => Err(ParseError {
245 message: format!(
246 "Unsupported CREATE statement type: {:?}",
247 self.peek_at_offset(offset)
248 ),
249 }),
250 }
251 }
252
253 fn parse_drop_statement(&mut self) -> Result<Statement<'arena>, ParseError> {
255 match self.peek_at_offset(1) {
257 Token::Keyword(Keyword::Table) => {
258 let stmt = self.parse_drop_table_statement()?;
259 Ok(Statement::DropTable(stmt))
260 }
261 Token::Keyword(Keyword::Index) => {
262 let stmt = self.parse_drop_index_statement()?;
263 Ok(Statement::DropIndex(stmt))
264 }
265 Token::Keyword(Keyword::View) => {
266 let stmt = self.parse_drop_view_statement()?;
267 Ok(Statement::DropView(stmt))
268 }
269 _ => Err(ParseError {
270 message: format!(
271 "Unsupported DROP statement type: {:?}",
272 self.peek_at_offset(1)
273 ),
274 }),
275 }
276 }
277
278 pub fn parse_expression_sql(
280 input: &str,
281 arena: &'arena Bump,
282 ) -> Result<&'arena Expression<'arena>, ParseError> {
283 let mut lexer = Lexer::new(input);
284 let tokens = lexer
285 .tokenize()
286 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
287
288 let mut parser = ArenaParser::new(tokens, arena);
289 let expr = parser.parse_expression()?;
290 Ok(arena.alloc(expr))
291 }
292
293 pub fn parse_alter_table_sql(
295 input: &str,
296 arena: &'arena Bump,
297 ) -> Result<&'arena AlterTableStmt<'arena>, ParseError> {
298 let mut lexer = Lexer::new(input);
299 let tokens = lexer
300 .tokenize()
301 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
302
303 let mut parser = ArenaParser::new(tokens, arena);
304 parser.parse_alter_table_statement()
305 }
306
307 pub fn parse_insert(
309 input: &str,
310 arena: &'arena Bump,
311 ) -> Result<&'arena InsertStmt<'arena>, ParseError> {
312 let mut lexer = Lexer::new(input);
313 let tokens = lexer
314 .tokenize()
315 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
316
317 let mut parser = ArenaParser::new(tokens, arena);
318 parser.parse_insert_statement()
319 }
320
321 pub fn parse_update(
323 input: &str,
324 arena: &'arena Bump,
325 ) -> Result<&'arena UpdateStmt<'arena>, ParseError> {
326 let mut lexer = Lexer::new(input);
327 let tokens = lexer
328 .tokenize()
329 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
330
331 let mut parser = ArenaParser::new(tokens, arena);
332 parser.parse_update_statement()
333 }
334
335 pub fn parse_delete(
337 input: &str,
338 arena: &'arena Bump,
339 ) -> Result<&'arena DeleteStmt<'arena>, ParseError> {
340 let mut lexer = Lexer::new(input);
341 let tokens = lexer
342 .tokenize()
343 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
344
345 let mut parser = ArenaParser::new(tokens, arena);
346 parser.parse_delete_statement()
347 }
348
349 pub fn parse_replace(
351 input: &str,
352 arena: &'arena Bump,
353 ) -> Result<&'arena InsertStmt<'arena>, ParseError> {
354 let mut lexer = Lexer::new(input);
355 let tokens = lexer
356 .tokenize()
357 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
358
359 let mut parser = ArenaParser::new(tokens, arena);
360 parser.parse_replace_statement()
361 }
362
363 pub fn parse_alter_table_sql_with_interner(
365 input: &str,
366 arena: &'arena Bump,
367 ) -> Result<(&'arena AlterTableStmt<'arena>, ArenaInterner<'arena>), ParseError> {
368 let mut lexer = Lexer::new(input);
369 let tokens = lexer
370 .tokenize()
371 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
372
373 let mut parser = ArenaParser::new(tokens, arena);
374 let stmt = parser.parse_alter_table_statement()?;
375 Ok((stmt, parser.into_interner()))
376 }
377
378 pub fn parse_delete_with_interner(
380 input: &str,
381 arena: &'arena Bump,
382 ) -> Result<(&'arena DeleteStmt<'arena>, ArenaInterner<'arena>), ParseError> {
383 let mut lexer = Lexer::new(input);
384 let tokens = lexer
385 .tokenize()
386 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
387
388 let mut parser = ArenaParser::new(tokens, arena);
389 let stmt = parser.parse_delete_statement()?;
390 Ok((stmt, parser.into_interner()))
391 }
392
393 pub fn parse_update_with_interner(
395 input: &str,
396 arena: &'arena Bump,
397 ) -> Result<(&'arena UpdateStmt<'arena>, ArenaInterner<'arena>), ParseError> {
398 let mut lexer = Lexer::new(input);
399 let tokens = lexer
400 .tokenize()
401 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
402
403 let mut parser = ArenaParser::new(tokens, arena);
404 let stmt = parser.parse_update_statement()?;
405 Ok((stmt, parser.into_interner()))
406 }
407
408 pub fn parse_insert_with_interner(
410 input: &str,
411 arena: &'arena Bump,
412 ) -> Result<(&'arena InsertStmt<'arena>, ArenaInterner<'arena>), ParseError> {
413 let mut lexer = Lexer::new(input);
414 let tokens = lexer
415 .tokenize()
416 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
417
418 let mut parser = ArenaParser::new(tokens, arena);
419 let stmt = parser.parse_insert_statement()?;
420 Ok((stmt, parser.into_interner()))
421 }
422
423 pub fn parse_replace_with_interner(
425 input: &str,
426 arena: &'arena Bump,
427 ) -> Result<(&'arena InsertStmt<'arena>, ArenaInterner<'arena>), ParseError> {
428 let mut lexer = Lexer::new(input);
429 let tokens = lexer
430 .tokenize()
431 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
432
433 let mut parser = ArenaParser::new(tokens, arena);
434 let stmt = parser.parse_replace_statement()?;
435 Ok((stmt, parser.into_interner()))
436 }
437
438 #[inline]
440 pub(crate) fn intern(&mut self, s: &str) -> Symbol {
441 self.interner.intern(s)
442 }
443
444 #[inline]
446 #[allow(dead_code)]
447 pub(crate) fn alloc_str(&self, s: &str) -> &'arena str {
448 self.arena.alloc_str(s)
449 }
450
451 #[inline]
453 #[allow(dead_code)]
454 pub(crate) fn arena(&self) -> &'arena Bump {
455 self.arena
456 }
457
458 pub(crate) fn peek(&self) -> &Token {
464 self.tokens.get(self.position).unwrap_or(&Token::Eof)
465 }
466
467 #[allow(dead_code)]
469 pub(crate) fn peek_next(&self) -> &Token {
470 self.tokens.get(self.position + 1).unwrap_or(&Token::Eof)
471 }
472
473 #[allow(dead_code)]
475 pub(crate) fn peek_at_offset(&self, offset: usize) -> &Token {
476 self.tokens.get(self.position + offset).unwrap_or(&Token::Eof)
477 }
478
479 pub(crate) fn advance(&mut self) {
481 if self.position < self.tokens.len() {
482 self.position += 1;
483 }
484 }
485
486 pub(crate) fn peek_keyword(&self, keyword: Keyword) -> bool {
488 matches!(self.peek(), Token::Keyword(kw) if *kw == keyword)
489 }
490
491 #[allow(dead_code)]
493 pub(crate) fn peek_next_keyword(&self, keyword: Keyword) -> bool {
494 matches!(self.peek_next(), Token::Keyword(kw) if *kw == keyword)
495 }
496
497 pub(crate) fn consume_keyword(&mut self, keyword: Keyword) -> Result<(), ParseError> {
499 if self.peek_keyword(keyword) {
500 self.advance();
501 Ok(())
502 } else {
503 Err(ParseError {
504 message: format!("Expected keyword {:?}, found {:?}", keyword, self.peek()),
505 })
506 }
507 }
508
509 pub(crate) fn try_consume_keyword(&mut self, keyword: Keyword) -> bool {
511 if self.peek_keyword(keyword) {
512 self.advance();
513 true
514 } else {
515 false
516 }
517 }
518
519 pub(crate) fn expect_keyword(&mut self, keyword: Keyword) -> Result<(), ParseError> {
521 self.consume_keyword(keyword)
522 }
523
524 pub(crate) fn expect_token(&mut self, expected: Token) -> Result<(), ParseError> {
526 if self.peek() == &expected {
527 self.advance();
528 Ok(())
529 } else {
530 Err(ParseError {
531 message: format!("Expected {:?}, found {:?}", expected, self.peek()),
532 })
533 }
534 }
535
536 pub(crate) fn try_consume(&mut self, token: &Token) -> bool {
538 if self.peek() == token {
539 self.advance();
540 true
541 } else {
542 false
543 }
544 }
545
546 pub(crate) fn next_placeholder(&mut self) -> usize {
548 let index = self.placeholder_count;
549 self.placeholder_count += 1;
550 index
551 }
552
553 pub(crate) fn parse_arena_identifier(&mut self) -> Result<Symbol, ParseError> {
559 match self.peek() {
560 Token::Identifier(name) => {
561 let name = name.clone();
562 self.advance();
563 Ok(self.intern(&name))
564 }
565 _ => Err(ParseError {
566 message: format!("Expected identifier, found {:?}", self.peek()),
567 }),
568 }
569 }
570
571 pub(crate) fn parse_identifier_list(
573 &mut self,
574 ) -> Result<bumpalo::collections::Vec<'arena, Symbol>, ParseError> {
575 let mut list = bumpalo::collections::Vec::new_in(self.arena);
576 loop {
577 list.push(self.parse_arena_identifier()?);
578 if !self.try_consume(&Token::Comma) {
579 break;
580 }
581 }
582 Ok(list)
583 }
584
585 pub(crate) fn parse_column_alias_list(
593 &mut self,
594 ) -> Result<Option<bumpalo::collections::Vec<'arena, Symbol>>, ParseError> {
595 if !self.try_consume(&Token::LParen) {
597 return Ok(None);
598 }
599
600 let mut aliases = bumpalo::collections::Vec::new_in(self.arena);
601
602 if self.try_consume(&Token::RParen) {
604 return Ok(Some(aliases));
605 }
606
607 aliases.push(self.parse_alias_name_symbol()?);
609
610 while self.try_consume(&Token::Comma) {
612 aliases.push(self.parse_alias_name_symbol()?);
613 }
614
615 self.expect_token(Token::RParen)?;
617
618 Ok(Some(aliases))
619 }
620
621 fn parse_alias_name_symbol(&mut self) -> Result<Symbol, ParseError> {
623 match self.peek() {
624 Token::Identifier(name) => {
625 let name = name.clone();
626 self.advance();
627 Ok(self.intern(&name))
628 }
629 Token::Keyword(kw) => {
630 let name = kw.to_string();
632 self.advance();
633 Ok(self.intern(&name))
634 }
635 _ => Err(ParseError {
636 message: format!("Expected alias name, found {:?}", self.peek()),
637 }),
638 }
639 }
640}
641
642pub fn parse_select_to_owned(input: &str) -> Result<vibesql_ast::SelectStmt, ParseError> {
668 let arena = Bump::new();
669 let mut lexer = Lexer::new(input);
670 let tokens = lexer
671 .tokenize()
672 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
673
674 let mut parser = ArenaParser::new(tokens, &arena);
675 let arena_stmt = parser.parse_select_statement()?;
676 let converter = Converter::new(parser.interner());
677 Ok(converter.convert_select(arena_stmt))
678}
679
680pub fn parse_expression_to_owned(input: &str) -> Result<vibesql_ast::Expression, ParseError> {
693 let arena = Bump::new();
694 let mut lexer = Lexer::new(input);
695 let tokens = lexer
696 .tokenize()
697 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
698
699 let mut parser = ArenaParser::new(tokens, &arena);
700 let arena_expr = parser.parse_expression()?;
701 let converter = Converter::new(parser.interner());
702 Ok(converter.convert_expression(&arena_expr))
703}
704
705pub fn parse_insert_to_owned(input: &str) -> Result<vibesql_ast::InsertStmt, ParseError> {
718 let arena = Bump::new();
719 let mut lexer = Lexer::new(input);
720 let tokens = lexer
721 .tokenize()
722 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
723
724 let mut parser = ArenaParser::new(tokens, &arena);
725 let arena_stmt = parser.parse_insert_statement()?;
726 let converter = Converter::new(parser.interner());
727 Ok(converter.convert_insert(arena_stmt))
728}
729
730pub fn parse_update_to_owned(input: &str) -> Result<vibesql_ast::UpdateStmt, ParseError> {
743 let arena = Bump::new();
744 let mut lexer = Lexer::new(input);
745 let tokens = lexer
746 .tokenize()
747 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
748
749 let mut parser = ArenaParser::new(tokens, &arena);
750 let arena_stmt = parser.parse_update_statement()?;
751 let converter = Converter::new(parser.interner());
752 Ok(converter.convert_update(arena_stmt))
753}
754
755pub fn parse_delete_to_owned(input: &str) -> Result<vibesql_ast::DeleteStmt, ParseError> {
768 let arena = Bump::new();
769 let mut lexer = Lexer::new(input);
770 let tokens = lexer
771 .tokenize()
772 .map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
773
774 let mut parser = ArenaParser::new(tokens, &arena);
775 let arena_stmt = parser.parse_delete_statement()?;
776 let converter = Converter::new(parser.interner());
777 Ok(converter.convert_delete(arena_stmt))
778}
779
780#[cfg(test)]
781mod tests {
782 use super::*;
783 use vibesql_ast::arena::Expression;
784 use vibesql_types::SqlValue;
785
786 #[test]
787 fn test_date_literal() {
788 let arena = Bump::new();
789 let expr = ArenaParser::parse_expression_sql("DATE '1998-12-01'", &arena).unwrap();
790 match expr {
791 Expression::Literal(SqlValue::Date(d)) => {
792 assert_eq!(d.year, 1998);
793 assert_eq!(d.month, 12);
794 assert_eq!(d.day, 1);
795 }
796 _ => panic!("Expected Date literal, got {:?}", expr),
797 }
798 }
799
800 #[test]
801 fn test_time_literal() {
802 let arena = Bump::new();
803 let expr = ArenaParser::parse_expression_sql("TIME '12:30:45'", &arena).unwrap();
804 match expr {
805 Expression::Literal(SqlValue::Time(t)) => {
806 assert_eq!(t.hour, 12);
807 assert_eq!(t.minute, 30);
808 assert_eq!(t.second, 45);
809 }
810 _ => panic!("Expected Time literal, got {:?}", expr),
811 }
812 }
813
814 #[test]
815 fn test_timestamp_literal() {
816 let arena = Bump::new();
817 let expr = ArenaParser::parse_expression_sql("TIMESTAMP '2024-01-15 10:30:00'", &arena).unwrap();
818 match expr {
819 Expression::Literal(SqlValue::Timestamp(ts)) => {
820 assert_eq!(ts.date.year, 2024);
821 assert_eq!(ts.date.month, 1);
822 assert_eq!(ts.date.day, 15);
823 }
824 _ => panic!("Expected Timestamp literal, got {:?}", expr),
825 }
826 }
827
828 #[test]
829 fn test_interval_literal() {
830 let arena = Bump::new();
831 let expr = ArenaParser::parse_expression_sql("INTERVAL '90' DAY", &arena).unwrap();
832 assert!(matches!(expr, Expression::Literal(SqlValue::Interval(_))));
834 }
835
836 #[test]
837 fn test_date_minus_interval_expression() {
838 let arena = Bump::new();
839 let expr = ArenaParser::parse_expression_sql("DATE '1998-12-01' - INTERVAL '90' DAY", &arena).unwrap();
840 match expr {
841 Expression::BinaryOp { op, left, right } => {
842 assert_eq!(*op, vibesql_ast::BinaryOperator::Minus);
843 assert!(matches!(left, Expression::Literal(SqlValue::Date(_))));
844 assert!(matches!(right, Expression::Literal(SqlValue::Interval(_))));
845 }
846 _ => panic!("Expected BinaryOp, got {:?}", expr),
847 }
848 }
849
850 #[test]
851 fn test_tpch_q1_parses() {
852 let arena = Bump::new();
853 let sql = r#"SELECT
854 l_returnflag,
855 l_linestatus,
856 SUM(l_quantity) AS sum_qty,
857 SUM(l_extendedprice) AS sum_base_price,
858 SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
859 SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
860 AVG(l_quantity) AS avg_qty,
861 AVG(l_extendedprice) AS avg_price,
862 AVG(l_discount) AS avg_disc,
863 COUNT(*) AS count_order
864 FROM
865 lineitem
866 WHERE
867 l_shipdate <= DATE '1998-12-01' - INTERVAL '90' DAY
868 GROUP BY
869 l_returnflag,
870 l_linestatus
871 ORDER BY
872 l_returnflag,
873 l_linestatus"#;
874
875 let result = ArenaParser::parse_sql(sql, &arena);
877 assert!(result.is_ok(), "TPC-H Q1 should parse successfully: {:?}", result.err());
878 }
879}