1use std::fmt;
2
3use crate::{keywords::Keyword, lexer::Lexer, token::Token};
4
5pub const MAX_ORDER_BY_TERMS: usize = 2000;
9
10mod advanced_objects;
11mod alter;
12mod create;
13mod cursor;
14mod delete;
15mod domain;
16mod drop;
17mod expressions;
18mod grant;
19mod helpers;
20mod index;
21mod insert;
22mod introspection;
23mod prepared;
24mod revoke;
25mod role;
26mod schema;
27mod select;
28mod table_options;
29mod transaction;
30mod trigger;
31mod truncate;
32mod update;
33mod view;
34
35#[derive(Debug, Clone, PartialEq)]
37pub struct ParseError {
38 pub message: String,
39}
40
41impl fmt::Display for ParseError {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(f, "Parse error: {}", self.message)
44 }
45}
46
47pub struct Parser {
49 tokens: Vec<Token>,
50 position: usize,
51 placeholder_count: usize,
54}
55
56impl Parser {
57 pub fn new(tokens: Vec<Token>) -> Self {
59 Parser { tokens, position: 0, placeholder_count: 0 }
60 }
61
62 pub fn parse_comma_separated_list<T, F>(&mut self, parse_item: F) -> Result<Vec<T>, ParseError>
84 where
85 F: Fn(&mut Self) -> Result<T, ParseError>,
86 {
87 let mut items = Vec::new();
88
89 items.push(parse_item(self)?);
91
92 while matches!(self.peek(), Token::Comma) {
94 self.advance(); items.push(parse_item(self)?);
96 }
97
98 Ok(items)
99 }
100
101 pub fn parse_sql(input: &str) -> Result<vibesql_ast::Statement, ParseError> {
103 let mut lexer = Lexer::new(input);
104 let tokens =
105 lexer.tokenize().map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
106
107 let mut parser = Parser::new(tokens);
108 parser.parse_statement()
109 }
110
111 pub fn parse_statement(&mut self) -> Result<vibesql_ast::Statement, ParseError> {
113 match self.peek() {
114 Token::Keyword { keyword: Keyword::Select, .. } => {
115 let select_stmt = self.parse_select_statement()?;
116 Ok(vibesql_ast::Statement::Select(Box::new(select_stmt)))
117 }
118 Token::Keyword { keyword: Keyword::With, .. } => {
119 self.parse_with_statement()
122 }
123 Token::Keyword { keyword: Keyword::Values, .. } => {
124 let select_stmt = self.parse_values_statement()?;
125 Ok(vibesql_ast::Statement::Select(Box::new(select_stmt)))
126 }
127 Token::Keyword { keyword: Keyword::Insert, .. } => {
128 let insert_stmt = self.parse_insert_statement()?;
129 Ok(vibesql_ast::Statement::Insert(insert_stmt))
130 }
131 Token::Keyword { keyword: Keyword::Replace, .. } => {
132 let insert_stmt = self.parse_replace_statement()?;
133 Ok(vibesql_ast::Statement::Insert(insert_stmt))
134 }
135 Token::Keyword { keyword: Keyword::Update, .. } => {
136 let update_stmt = self.parse_update_statement()?;
137 Ok(vibesql_ast::Statement::Update(update_stmt))
138 }
139 Token::Keyword { keyword: Keyword::Delete, .. } => {
140 let delete_stmt = self.parse_delete_statement()?;
141 Ok(vibesql_ast::Statement::Delete(delete_stmt))
142 }
143 Token::Keyword { keyword: Keyword::Create, .. } => {
144 if self.peek_next_keyword(Keyword::Or)
146 && matches!(
147 self.peek_at_offset(2),
148 Token::Keyword { keyword: Keyword::Replace, .. }
149 )
150 {
151 if matches!(
153 self.peek_at_offset(3),
154 Token::Keyword { keyword: Keyword::View, .. }
155 ) || matches!(
156 self.peek_at_offset(3),
157 Token::Keyword { keyword: Keyword::Temp, .. }
158 ) || matches!(
159 self.peek_at_offset(3),
160 Token::Keyword { keyword: Keyword::Temporary, .. }
161 ) {
162 return Ok(vibesql_ast::Statement::CreateView(
163 self.parse_create_view_statement()?,
164 ));
165 }
166 }
167 if self.peek_next_keyword(Keyword::Table) {
168 Ok(vibesql_ast::Statement::CreateTable(self.parse_create_table_statement()?))
169 } else if self.peek_next_keyword(Keyword::Schema) {
170 Ok(vibesql_ast::Statement::CreateSchema(self.parse_create_schema_statement()?))
171 } else if self.peek_next_keyword(Keyword::Role) {
172 Ok(vibesql_ast::Statement::CreateRole(self.parse_create_role_statement()?))
173 } else if self.peek_next_keyword(Keyword::Domain) {
174 Ok(vibesql_ast::Statement::CreateDomain(self.parse_create_domain_statement()?))
175 } else if self.peek_next_keyword(Keyword::Sequence) {
176 Ok(vibesql_ast::Statement::CreateSequence(
177 self.parse_create_sequence_statement()?,
178 ))
179 } else if self.peek_next_keyword(Keyword::Type) {
180 Ok(vibesql_ast::Statement::CreateType(self.parse_create_type_statement()?))
181 } else if self.peek_next_keyword(Keyword::Collation) {
182 Ok(vibesql_ast::Statement::CreateCollation(
183 self.parse_create_collation_statement()?,
184 ))
185 } else if self.peek_next_keyword(Keyword::Character) {
186 Ok(vibesql_ast::Statement::CreateCharacterSet(
187 self.parse_create_character_set_statement()?,
188 ))
189 } else if self.peek_next_keyword(Keyword::Translation) {
190 Ok(vibesql_ast::Statement::CreateTranslation(
191 self.parse_create_translation_statement()?,
192 ))
193 } else if self.peek_next_keyword(Keyword::View) {
194 Ok(vibesql_ast::Statement::CreateView(self.parse_create_view_statement()?))
195 } else if self.peek_next_keyword(Keyword::Temp)
196 || self.peek_next_keyword(Keyword::Temporary)
197 {
198 if matches!(
201 self.peek_at_offset(2),
202 Token::Keyword { keyword: Keyword::Table, .. }
203 ) {
204 Ok(vibesql_ast::Statement::CreateTable(
205 self.parse_create_table_statement()?,
206 ))
207 } else {
208 Ok(vibesql_ast::Statement::CreateView(self.parse_create_view_statement()?))
209 }
210 } else if self.peek_next_keyword(Keyword::Trigger) {
211 Ok(vibesql_ast::Statement::CreateTrigger(
212 self.parse_create_trigger_statement()?,
213 ))
214 } else if self.peek_next_keyword(Keyword::Index)
215 || self.peek_next_keyword(Keyword::Unique)
216 || self.peek_next_keyword(Keyword::Fulltext)
217 || self.peek_next_keyword(Keyword::Spatial)
218 {
219 Ok(vibesql_ast::Statement::CreateIndex(self.parse_create_index_statement()?))
220 } else if self.peek_next_keyword(Keyword::Assertion) {
221 Ok(vibesql_ast::Statement::CreateAssertion(
222 self.parse_create_assertion_statement()?,
223 ))
224 } else if self.peek_next_keyword(Keyword::Procedure) {
225 Ok(vibesql_ast::Statement::CreateProcedure(
226 self.parse_create_procedure_statement()?,
227 ))
228 } else if self.peek_next_keyword(Keyword::Function) {
229 Ok(vibesql_ast::Statement::CreateFunction(
230 self.parse_create_function_statement()?,
231 ))
232 } else {
233 Err(ParseError {
234 message:
235 "Expected TABLE, SCHEMA, ROLE, DOMAIN, SEQUENCE, TYPE, COLLATION, CHARACTER, TRANSLATION, VIEW, TRIGGER, INDEX, ASSERTION, PROCEDURE, or FUNCTION after CREATE"
236 .to_string(),
237 })
238 }
239 }
240 Token::Keyword { keyword: Keyword::Drop, .. } => {
241 if self.peek_next_keyword(Keyword::Table) {
242 Ok(vibesql_ast::Statement::DropTable(self.parse_drop_table_statement()?))
243 } else if self.peek_next_keyword(Keyword::Schema) {
244 Ok(vibesql_ast::Statement::DropSchema(self.parse_drop_schema_statement()?))
245 } else if self.peek_next_keyword(Keyword::Role) {
246 Ok(vibesql_ast::Statement::DropRole(self.parse_drop_role_statement()?))
247 } else if self.peek_next_keyword(Keyword::Domain) {
248 Ok(vibesql_ast::Statement::DropDomain(self.parse_drop_domain_statement()?))
249 } else if self.peek_next_keyword(Keyword::Sequence) {
250 Ok(vibesql_ast::Statement::DropSequence(self.parse_drop_sequence_statement()?))
251 } else if self.peek_next_keyword(Keyword::Type) {
252 Ok(vibesql_ast::Statement::DropType(self.parse_drop_type_statement()?))
253 } else if self.peek_next_keyword(Keyword::Collation) {
254 Ok(vibesql_ast::Statement::DropCollation(
255 self.parse_drop_collation_statement()?,
256 ))
257 } else if self.peek_next_keyword(Keyword::Character) {
258 Ok(vibesql_ast::Statement::DropCharacterSet(
259 self.parse_drop_character_set_statement()?,
260 ))
261 } else if self.peek_next_keyword(Keyword::Translation) {
262 Ok(vibesql_ast::Statement::DropTranslation(
263 self.parse_drop_translation_statement()?,
264 ))
265 } else if self.peek_next_keyword(Keyword::View) {
266 Ok(vibesql_ast::Statement::DropView(self.parse_drop_view_statement()?))
267 } else if self.peek_next_keyword(Keyword::Trigger) {
268 Ok(vibesql_ast::Statement::DropTrigger(self.parse_drop_trigger_statement()?))
269 } else if self.peek_next_keyword(Keyword::Index) {
270 Ok(vibesql_ast::Statement::DropIndex(self.parse_drop_index_statement()?))
271 } else if self.peek_next_keyword(Keyword::Assertion) {
272 Ok(vibesql_ast::Statement::DropAssertion(
273 self.parse_drop_assertion_statement()?,
274 ))
275 } else if self.peek_next_keyword(Keyword::Procedure) {
276 Ok(vibesql_ast::Statement::DropProcedure(
277 self.parse_drop_procedure_statement()?,
278 ))
279 } else if self.peek_next_keyword(Keyword::Function) {
280 Ok(vibesql_ast::Statement::DropFunction(self.parse_drop_function_statement()?))
281 } else {
282 Err(ParseError {
283 message:
284 "Expected TABLE, SCHEMA, ROLE, DOMAIN, SEQUENCE, TYPE, COLLATION, CHARACTER, TRANSLATION, VIEW, TRIGGER, INDEX, ASSERTION, PROCEDURE, or FUNCTION after DROP"
285 .to_string(),
286 })
287 }
288 }
289 Token::Keyword { keyword: Keyword::Truncate, .. } => {
290 let truncate_stmt = self.parse_truncate_table_statement()?;
291 Ok(vibesql_ast::Statement::TruncateTable(truncate_stmt))
292 }
293 Token::Keyword { keyword: Keyword::Alter, .. } => {
294 if self.peek_next_keyword(Keyword::Table) {
295 let alter_stmt = self.parse_alter_table_statement()?;
296 Ok(vibesql_ast::Statement::AlterTable(alter_stmt))
297 } else if self.peek_next_keyword(Keyword::Sequence) {
298 let alter_stmt = self.parse_alter_sequence_statement()?;
299 Ok(vibesql_ast::Statement::AlterSequence(alter_stmt))
300 } else if self.peek_next_keyword(Keyword::Trigger) {
301 let alter_stmt = self.parse_alter_trigger_statement()?;
302 Ok(vibesql_ast::Statement::AlterTrigger(alter_stmt))
303 } else {
304 Err(ParseError {
305 message: "Expected TABLE, SEQUENCE, or TRIGGER after ALTER".to_string(),
306 })
307 }
308 }
309 Token::Keyword { keyword: Keyword::Reindex, .. } => {
310 let reindex_stmt = self.parse_reindex_statement()?;
311 Ok(vibesql_ast::Statement::Reindex(reindex_stmt))
312 }
313 Token::Keyword { keyword: Keyword::Analyze, .. } => {
314 let analyze_stmt = self.parse_analyze_statement()?;
315 Ok(vibesql_ast::Statement::Analyze(analyze_stmt))
316 }
317 Token::Keyword { keyword: Keyword::Explain, .. } => {
318 let explain_stmt = self.parse_explain_statement()?;
319 Ok(vibesql_ast::Statement::Explain(explain_stmt))
320 }
321 Token::Keyword { keyword: Keyword::Begin, .. }
322 | Token::Keyword { keyword: Keyword::Start, .. } => {
323 let begin_stmt = self.parse_begin_statement()?;
324 Ok(vibesql_ast::Statement::BeginTransaction(begin_stmt))
325 }
326 Token::Keyword { keyword: Keyword::Commit, .. }
327 | Token::Keyword { keyword: Keyword::End, .. } => {
328 let commit_stmt = self.parse_commit_statement()?;
330 Ok(vibesql_ast::Statement::Commit(commit_stmt))
331 }
332 Token::Keyword { keyword: Keyword::Rollback, .. } => {
333 let saved_position = self.position;
335 self.advance(); if self.peek_keyword(Keyword::To) {
337 self.position = saved_position;
339 let rollback_to_stmt = self.parse_rollback_to_savepoint_statement()?;
340 Ok(vibesql_ast::Statement::RollbackToSavepoint(rollback_to_stmt))
341 } else {
342 self.position = saved_position;
344 let rollback_stmt = self.parse_rollback_statement()?;
345 Ok(vibesql_ast::Statement::Rollback(rollback_stmt))
346 }
347 }
348 Token::Keyword { keyword: Keyword::Savepoint, .. } => {
349 let savepoint_stmt = self.parse_savepoint_statement()?;
350 Ok(vibesql_ast::Statement::Savepoint(savepoint_stmt))
351 }
352 Token::Keyword { keyword: Keyword::Release, .. } => {
353 let release_stmt = self.parse_release_savepoint_statement()?;
354 Ok(vibesql_ast::Statement::ReleaseSavepoint(release_stmt))
355 }
356 Token::Keyword { keyword: Keyword::Set, .. } => {
357 if self.peek_next_keyword(Keyword::Schema) {
359 let set_stmt = self.parse_set_schema_statement()?;
360 Ok(vibesql_ast::Statement::SetSchema(set_stmt))
361 } else if self.peek_next_keyword(Keyword::Catalog) {
362 let set_stmt = schema::parse_set_catalog(self)?;
363 Ok(vibesql_ast::Statement::SetCatalog(set_stmt))
364 } else if self.peek_next_keyword(Keyword::Names) {
365 let set_stmt = schema::parse_set_names(self)?;
366 Ok(vibesql_ast::Statement::SetNames(set_stmt))
367 } else if self.peek_next_keyword(Keyword::Time) {
368 let set_stmt = schema::parse_set_time_zone(self)?;
369 Ok(vibesql_ast::Statement::SetTimeZone(set_stmt))
370 } else if self.peek_next_keyword(Keyword::Transaction) {
371 let set_stmt = self.parse_set_transaction_statement()?;
372 Ok(vibesql_ast::Statement::SetTransaction(set_stmt))
373 } else if self.peek_next_keyword(Keyword::Local) {
374 let set_stmt = self.parse_set_transaction_statement()?;
376 Ok(vibesql_ast::Statement::SetTransaction(set_stmt))
377 } else {
378 let set_stmt = schema::parse_set_variable(self)?;
380 Ok(vibesql_ast::Statement::SetVariable(set_stmt))
381 }
382 }
383 Token::Keyword { keyword: Keyword::Grant, .. } => {
384 let grant_stmt = self.parse_grant_statement()?;
385 Ok(vibesql_ast::Statement::Grant(grant_stmt))
386 }
387 Token::Keyword { keyword: Keyword::Revoke, .. } => {
388 let revoke_stmt = self.parse_revoke_statement()?;
389 Ok(vibesql_ast::Statement::Revoke(revoke_stmt))
390 }
391 Token::Keyword { keyword: Keyword::Declare, .. } => {
392 let declare_cursor_stmt = self.parse_declare_cursor_statement()?;
393 Ok(vibesql_ast::Statement::DeclareCursor(declare_cursor_stmt))
394 }
395 Token::Keyword { keyword: Keyword::Open, .. } => {
396 let open_cursor_stmt = self.parse_open_cursor_statement()?;
397 Ok(vibesql_ast::Statement::OpenCursor(open_cursor_stmt))
398 }
399 Token::Keyword { keyword: Keyword::Fetch, .. } => {
400 let fetch_stmt = self.parse_fetch_statement()?;
401 Ok(vibesql_ast::Statement::Fetch(fetch_stmt))
402 }
403 Token::Keyword { keyword: Keyword::Close, .. } => {
404 let close_cursor_stmt = self.parse_close_cursor_statement()?;
405 Ok(vibesql_ast::Statement::CloseCursor(close_cursor_stmt))
406 }
407 Token::Keyword { keyword: Keyword::Call, .. } => {
408 let call_stmt = self.parse_call_statement()?;
409 Ok(vibesql_ast::Statement::Call(call_stmt))
410 }
411 Token::Keyword { keyword: Keyword::Show, .. } => self.parse_show_statement(),
412 Token::Keyword { keyword: Keyword::Describe, .. } => {
413 let describe_stmt = self.parse_describe_statement()?;
414 Ok(vibesql_ast::Statement::Describe(describe_stmt))
415 }
416 Token::Keyword { keyword: Keyword::Prepare, .. } => {
417 let prepare_stmt = self.parse_prepare_statement()?;
418 Ok(vibesql_ast::Statement::Prepare(prepare_stmt))
419 }
420 Token::Keyword { keyword: Keyword::Execute, .. } => {
421 let execute_stmt = self.parse_execute_statement()?;
422 Ok(vibesql_ast::Statement::Execute(execute_stmt))
423 }
424 Token::Keyword { keyword: Keyword::Deallocate, .. } => {
425 let deallocate_stmt = self.parse_deallocate_statement()?;
426 Ok(vibesql_ast::Statement::Deallocate(deallocate_stmt))
427 }
428 Token::Keyword { keyword: Keyword::Pragma, .. } => {
429 let pragma_stmt = self.parse_pragma_statement()?;
430 Ok(vibesql_ast::Statement::Pragma(pragma_stmt))
431 }
432 _ => Err(ParseError { message: self.peek().syntax_error() }),
433 }
434 }
435
436 pub fn parse_begin_statement(&mut self) -> Result<vibesql_ast::BeginStmt, ParseError> {
438 transaction::parse_begin_statement(self)
439 }
440
441 pub fn parse_commit_statement(&mut self) -> Result<vibesql_ast::CommitStmt, ParseError> {
443 transaction::parse_commit_statement(self)
444 }
445
446 pub fn parse_rollback_statement(&mut self) -> Result<vibesql_ast::RollbackStmt, ParseError> {
448 transaction::parse_rollback_statement(self)
449 }
450
451 pub fn parse_alter_table_statement(
453 &mut self,
454 ) -> Result<vibesql_ast::AlterTableStmt, ParseError> {
455 alter::parse_alter_table(self)
456 }
457
458 pub fn parse_savepoint_statement(&mut self) -> Result<vibesql_ast::SavepointStmt, ParseError> {
460 transaction::parse_savepoint_statement(self)
461 }
462
463 pub fn parse_rollback_to_savepoint_statement(
465 &mut self,
466 ) -> Result<vibesql_ast::RollbackToSavepointStmt, ParseError> {
467 transaction::parse_rollback_to_savepoint_statement(self)
468 }
469
470 pub fn parse_release_savepoint_statement(
472 &mut self,
473 ) -> Result<vibesql_ast::ReleaseSavepointStmt, ParseError> {
474 transaction::parse_release_savepoint_statement(self)
475 }
476
477 pub fn parse_create_schema_statement(
479 &mut self,
480 ) -> Result<vibesql_ast::CreateSchemaStmt, ParseError> {
481 schema::parse_create_schema(self)
482 }
483
484 pub fn parse_drop_schema_statement(
486 &mut self,
487 ) -> Result<vibesql_ast::DropSchemaStmt, ParseError> {
488 schema::parse_drop_schema(self)
489 }
490
491 pub fn parse_set_schema_statement(&mut self) -> Result<vibesql_ast::SetSchemaStmt, ParseError> {
493 schema::parse_set_schema(self)
494 }
495
496 pub fn parse_grant_statement(&mut self) -> Result<vibesql_ast::GrantStmt, ParseError> {
498 grant::parse_grant(self)
499 }
500
501 pub fn parse_revoke_statement(&mut self) -> Result<vibesql_ast::RevokeStmt, ParseError> {
503 revoke::parse_revoke(self)
504 }
505
506 pub fn parse_create_role_statement(
508 &mut self,
509 ) -> Result<vibesql_ast::CreateRoleStmt, ParseError> {
510 role::parse_create_role(self)
511 }
512
513 pub fn parse_drop_role_statement(&mut self) -> Result<vibesql_ast::DropRoleStmt, ParseError> {
515 role::parse_drop_role(self)
516 }
517
518 pub fn parse_create_domain_statement(
524 &mut self,
525 ) -> Result<vibesql_ast::CreateDomainStmt, ParseError> {
526 domain::parse_create_domain(self)
527 }
528
529 pub fn parse_drop_domain_statement(
531 &mut self,
532 ) -> Result<vibesql_ast::DropDomainStmt, ParseError> {
533 domain::parse_drop_domain(self)
534 }
535
536 pub fn parse_create_sequence_statement(
538 &mut self,
539 ) -> Result<vibesql_ast::CreateSequenceStmt, ParseError> {
540 advanced_objects::parse_create_sequence(self)
541 }
542
543 pub fn parse_drop_sequence_statement(
545 &mut self,
546 ) -> Result<vibesql_ast::DropSequenceStmt, ParseError> {
547 advanced_objects::parse_drop_sequence(self)
548 }
549
550 pub fn parse_alter_sequence_statement(
552 &mut self,
553 ) -> Result<vibesql_ast::AlterSequenceStmt, ParseError> {
554 advanced_objects::parse_alter_sequence(self)
555 }
556
557 pub fn parse_create_type_statement(
559 &mut self,
560 ) -> Result<vibesql_ast::CreateTypeStmt, ParseError> {
561 advanced_objects::parse_create_type(self)
562 }
563
564 pub fn parse_set_transaction_statement(
566 &mut self,
567 ) -> Result<vibesql_ast::SetTransactionStmt, ParseError> {
568 self.expect_keyword(Keyword::Set)?;
570
571 let local = self.try_consume_keyword(Keyword::Local);
573
574 self.expect_keyword(Keyword::Transaction)?;
576
577 let mut isolation_level = None;
579 let mut access_mode = None;
580
581 loop {
582 if self.try_consume_keyword(Keyword::Serializable) {
583 isolation_level = Some(vibesql_ast::IsolationLevel::Serializable);
584 } else if self.try_consume_keyword(Keyword::Read) {
585 if self.try_consume_keyword(Keyword::Only) {
586 access_mode = Some(vibesql_ast::TransactionAccessMode::ReadOnly);
587 } else if self.try_consume_keyword(Keyword::Write) {
588 access_mode = Some(vibesql_ast::TransactionAccessMode::ReadWrite);
589 } else {
590 return Err(ParseError {
591 message: "Expected ONLY or WRITE after READ".to_string(),
592 });
593 }
594 } else if self.try_consume_keyword(Keyword::Isolation) {
595 self.expect_keyword(Keyword::Level)?;
596 if self.try_consume_keyword(Keyword::Serializable) {
597 isolation_level = Some(vibesql_ast::IsolationLevel::Serializable);
598 } else {
599 return Err(ParseError {
600 message: "Expected SERIALIZABLE after ISOLATION LEVEL".to_string(),
601 });
602 }
603 } else {
604 break;
605 }
606
607 if !self.try_consume(&Token::Comma) {
609 break;
610 }
611 }
612
613 Ok(vibesql_ast::SetTransactionStmt { local, isolation_level, access_mode })
614 }
615
616 pub fn parse_drop_type_statement(&mut self) -> Result<vibesql_ast::DropTypeStmt, ParseError> {
618 advanced_objects::parse_drop_type(self)
619 }
620
621 pub fn parse_create_collation_statement(
623 &mut self,
624 ) -> Result<vibesql_ast::CreateCollationStmt, ParseError> {
625 advanced_objects::parse_create_collation(self)
626 }
627
628 pub fn parse_drop_collation_statement(
630 &mut self,
631 ) -> Result<vibesql_ast::DropCollationStmt, ParseError> {
632 advanced_objects::parse_drop_collation(self)
633 }
634
635 pub fn parse_create_character_set_statement(
637 &mut self,
638 ) -> Result<vibesql_ast::CreateCharacterSetStmt, ParseError> {
639 advanced_objects::parse_create_character_set(self)
640 }
641
642 pub fn parse_drop_character_set_statement(
644 &mut self,
645 ) -> Result<vibesql_ast::DropCharacterSetStmt, ParseError> {
646 advanced_objects::parse_drop_character_set(self)
647 }
648
649 pub fn parse_create_translation_statement(
651 &mut self,
652 ) -> Result<vibesql_ast::CreateTranslationStmt, ParseError> {
653 advanced_objects::parse_create_translation(self)
654 }
655
656 pub fn parse_drop_translation_statement(
658 &mut self,
659 ) -> Result<vibesql_ast::DropTranslationStmt, ParseError> {
660 advanced_objects::parse_drop_translation(self)
661 }
662
663 pub fn parse_create_assertion_statement(
665 &mut self,
666 ) -> Result<vibesql_ast::CreateAssertionStmt, ParseError> {
667 advanced_objects::parse_create_assertion(self)
668 }
669
670 pub fn parse_drop_assertion_statement(
672 &mut self,
673 ) -> Result<vibesql_ast::DropAssertionStmt, ParseError> {
674 advanced_objects::parse_drop_assertion(self)
675 }
676
677 pub fn parse_create_procedure_statement(
679 &mut self,
680 ) -> Result<vibesql_ast::CreateProcedureStmt, ParseError> {
681 self.advance(); self.advance(); self.parse_create_procedure()
684 }
685
686 pub fn parse_drop_procedure_statement(
688 &mut self,
689 ) -> Result<vibesql_ast::DropProcedureStmt, ParseError> {
690 self.advance(); self.advance(); self.parse_drop_procedure()
693 }
694
695 pub fn parse_create_function_statement(
697 &mut self,
698 ) -> Result<vibesql_ast::CreateFunctionStmt, ParseError> {
699 self.advance(); self.advance(); self.parse_create_function()
702 }
703
704 pub fn parse_drop_function_statement(
706 &mut self,
707 ) -> Result<vibesql_ast::DropFunctionStmt, ParseError> {
708 self.advance(); self.advance(); self.parse_drop_function()
711 }
712
713 pub fn parse_call_statement(&mut self) -> Result<vibesql_ast::CallStmt, ParseError> {
715 self.advance(); self.parse_call()
717 }
718
719 fn parse_with_statement(&mut self) -> Result<vibesql_ast::Statement, ParseError> {
725 self.consume_keyword(Keyword::With)?;
726
727 let recursive = if self.peek_keyword(Keyword::Recursive) {
729 self.consume_keyword(Keyword::Recursive)?;
730 true
731 } else {
732 false
733 };
734
735 let cte_list = self.parse_cte_list(recursive)?;
737
738 match self.peek() {
740 Token::Keyword { keyword: Keyword::Select, .. } => {
741 let mut select_stmt = self.parse_select_statement_after_with()?;
745 select_stmt.with_clause = Some(cte_list);
746 Ok(vibesql_ast::Statement::Select(Box::new(select_stmt)))
747 }
748 Token::Keyword { keyword: Keyword::Insert, .. } => {
749 let insert_stmt = self.parse_insert_statement_with_cte(cte_list)?;
751 Ok(vibesql_ast::Statement::Insert(insert_stmt))
752 }
753 Token::Keyword { keyword: Keyword::Update, .. } => {
754 let update_stmt = self.parse_update_statement_with_cte(cte_list)?;
756 Ok(vibesql_ast::Statement::Update(update_stmt))
757 }
758 Token::Keyword { keyword: Keyword::Delete, .. } => {
759 let delete_stmt = self.parse_delete_statement_with_cte(cte_list)?;
761 Ok(vibesql_ast::Statement::Delete(delete_stmt))
762 }
763 _ => Err(ParseError {
764 message: format!(
765 "Expected SELECT, INSERT, UPDATE, or DELETE after WITH clause, found {}",
766 self.peek().syntax_error()
767 ),
768 }),
769 }
770 }
771
772 fn parse_select_statement_after_with(&mut self) -> Result<vibesql_ast::SelectStmt, ParseError> {
775 self.expect_keyword(Keyword::Select)?;
776
777 let distinct = if self.peek_keyword(Keyword::Distinct) {
779 self.consume_keyword(Keyword::Distinct)?;
780 true
781 } else if self.peek_keyword(Keyword::All) {
782 self.consume_keyword(Keyword::All)?;
783 false
784 } else {
785 false
786 };
787
788 let select_list = self.parse_select_list()?;
790
791 let (into_table, into_variables) = if self.peek_keyword(Keyword::Into) {
793 self.consume_keyword(Keyword::Into)?;
794 if matches!(self.peek(), Token::UserVariable(_)) {
795 let variables = self.parse_comma_separated_list(|p| match p.peek() {
796 Token::UserVariable(var_name) => {
797 let name = var_name.clone();
798 p.advance();
799 Ok(name)
800 }
801 _ => Err(ParseError {
802 message: "Expected user variable (@var) in procedural SELECT INTO"
803 .to_string(),
804 }),
805 })?;
806 (None, Some(variables))
807 } else {
808 (Some(self.parse_identifier()?), None)
809 }
810 } else {
811 (None, None)
812 };
813
814 let from = if self.peek_keyword(Keyword::From) {
816 self.consume_keyword(Keyword::From)?;
817 Some(self.parse_from_clause()?)
818 } else {
819 None
820 };
821
822 let where_clause = if self.peek_keyword(Keyword::Where) {
824 self.consume_keyword(Keyword::Where)?;
825 Some(self.parse_expression()?)
826 } else {
827 None
828 };
829
830 let group_by = if self.peek_keyword(Keyword::Group) {
832 self.consume_keyword(Keyword::Group)?;
833 self.expect_keyword(Keyword::By)?;
834 Some(self.parse_group_by_clause()?)
835 } else {
836 None
837 };
838
839 let having = if self.peek_keyword(Keyword::Having) {
841 self.consume_keyword(Keyword::Having)?;
842 Some(self.parse_expression()?)
843 } else {
844 None
845 };
846
847 let set_operation = if self.peek_keyword(Keyword::Union)
849 || self.peek_keyword(Keyword::Intersect)
850 || self.peek_keyword(Keyword::Except)
851 {
852 let op = if self.peek_keyword(Keyword::Union) {
853 self.consume_keyword(Keyword::Union)?;
854 vibesql_ast::SetOperator::Union
855 } else if self.peek_keyword(Keyword::Intersect) {
856 self.consume_keyword(Keyword::Intersect)?;
857 vibesql_ast::SetOperator::Intersect
858 } else {
859 self.consume_keyword(Keyword::Except)?;
860 vibesql_ast::SetOperator::Except
861 };
862
863 let all = if self.peek_keyword(Keyword::All) {
864 self.consume_keyword(Keyword::All)?;
865 true
866 } else if self.peek_keyword(Keyword::Distinct) {
867 self.consume_keyword(Keyword::Distinct)?;
868 false
869 } else {
870 false
871 };
872
873 let right = if matches!(self.peek(), Token::LParen) {
874 self.advance();
875 let stmt = if self.peek_keyword(Keyword::Values) {
876 self.parse_values_statement()?
877 } else {
878 self.parse_select_statement()?
879 };
880 if !matches!(self.peek(), Token::RParen) {
881 return Err(ParseError {
882 message: "Expected ')' after parenthesized statement in set operation"
883 .to_string(),
884 });
885 }
886 self.advance();
887 Box::new(stmt)
888 } else if self.peek_keyword(Keyword::Values) {
889 Box::new(self.parse_values_statement()?)
890 } else {
891 Box::new(self.parse_select_statement()?)
892 };
893
894 Some(vibesql_ast::SetOperation { op, all, right })
895 } else {
896 None
897 };
898
899 let order_by = if self.peek_keyword(Keyword::Order) {
901 self.consume_keyword(Keyword::Order)?;
902 self.expect_keyword(Keyword::By)?;
903
904 let order_items = self.parse_comma_separated_list(|p| {
905 let expr = p.parse_expression()?;
906 let direction = if p.peek_keyword(Keyword::Asc) {
907 p.consume_keyword(Keyword::Asc)?;
908 vibesql_ast::OrderDirection::Asc
909 } else if p.peek_keyword(Keyword::Desc) {
910 p.consume_keyword(Keyword::Desc)?;
911 vibesql_ast::OrderDirection::Desc
912 } else {
913 vibesql_ast::OrderDirection::Asc
914 };
915
916 let nulls_order = if p.peek_keyword(Keyword::Nulls) {
917 p.consume_keyword(Keyword::Nulls)?;
918 if p.peek_keyword(Keyword::First) {
919 p.consume_keyword(Keyword::First)?;
920 Some(vibesql_ast::NullsOrder::First)
921 } else if p.peek_keyword(Keyword::Last) {
922 p.consume_keyword(Keyword::Last)?;
923 Some(vibesql_ast::NullsOrder::Last)
924 } else {
925 return Err(ParseError {
926 message: format!(
927 "Expected FIRST or LAST after NULLS, found {}",
928 p.peek().syntax_error()
929 ),
930 });
931 }
932 } else {
933 None
934 };
935
936 Ok(vibesql_ast::OrderByItem { expr, direction, nulls_order })
937 })?;
938
939 if order_items.len() > MAX_ORDER_BY_TERMS {
941 return Err(ParseError {
942 message: "too many terms in ORDER BY clause".to_string(),
943 });
944 }
945
946 Some(order_items)
947 } else {
948 None
949 };
950
951 let (limit, offset_from_limit) = if self.peek_keyword(Keyword::Limit) {
953 self.consume_keyword(Keyword::Limit)?;
954 let first_expr = self.parse_expression()?;
955
956 if matches!(self.peek(), Token::Comma) {
957 self.advance();
958 let second_expr = self.parse_expression()?;
959 (Some(second_expr), Some(first_expr))
960 } else {
961 (Some(first_expr), None)
962 }
963 } else {
964 (None, None)
965 };
966
967 let offset = if offset_from_limit.is_some() {
969 offset_from_limit
970 } else if self.peek_keyword(Keyword::Offset) {
971 self.consume_keyword(Keyword::Offset)?;
972 Some(self.parse_expression()?)
973 } else {
974 None
975 };
976
977 if matches!(self.peek(), Token::Semicolon) {
979 self.advance();
980 }
981
982 Ok(vibesql_ast::SelectStmt {
983 with_clause: None, distinct,
985 select_list,
986 into_table,
987 into_variables,
988 from,
989 where_clause,
990 group_by,
991 having,
992 order_by,
993 limit,
994 offset,
995 set_operation,
996 values: None,
997 })
998 }
999}