parseStatement parses a single SQL statement using O(1) Type-based dispatch. This is the statement routing function that examines the current token and dispatches to the appropriate specialized parser based on the statement type. It uses O(1) switch dispatch on Type (integer enum) which compiles to
()
| 566 | // |
| 567 | // Thread Safety: NOT thread-safe - operates on parser instance state. |
| 568 | func (p *Parser) parseStatement() (ast.Statement, error) { |
| 569 | // Check context if available |
| 570 | if p.ctx != nil { |
| 571 | if err := p.ctx.Err(); err != nil { |
| 572 | // Context cancellation is not a parsing error, return the context error directly |
| 573 | return nil, fmt.Errorf("parsing cancelled: %w", err) |
| 574 | } |
| 575 | } |
| 576 | |
| 577 | // O(1) switch dispatch on Token.Type (compiles to jump table). |
| 578 | // All tokens are normalized at parse entry so Type is always set. |
| 579 | switch p.currentToken.Token.Type { |
| 580 | case models.TokenTypeWith: |
| 581 | return p.parseWithStatement() |
| 582 | case models.TokenTypeSelect: |
| 583 | stmtPos := p.currentLocation() |
| 584 | p.advance() |
| 585 | stmt, err := p.parseSelectWithSetOperations() |
| 586 | if err != nil { |
| 587 | return nil, err |
| 588 | } |
| 589 | if ss, ok := stmt.(*ast.SelectStatement); ok { |
| 590 | if ss.Pos.IsZero() { |
| 591 | ss.Pos = stmtPos |
| 592 | } |
| 593 | } |
| 594 | // ClickHouse trailing SETTINGS k=v [, k=v]... on SELECT. Parse-only; |
| 595 | // the settings are consumed but not modeled on the AST. |
| 596 | if p.dialect == string(keywords.DialectClickHouse) && p.isTokenMatch("SETTINGS") { |
| 597 | p.advance() // SETTINGS |
| 598 | for { |
| 599 | t := p.currentToken.Token.Type |
| 600 | if t == models.TokenTypeEOF || t == models.TokenTypeSemicolon || |
| 601 | t == models.TokenTypeRParen { |
| 602 | break |
| 603 | } |
| 604 | p.advance() |
| 605 | } |
| 606 | } |
| 607 | return stmt, nil |
| 608 | case models.TokenTypeInsert: |
| 609 | stmtPos := p.currentLocation() |
| 610 | p.advance() |
| 611 | stmt, err := p.parseInsertStatement() |
| 612 | if err != nil { |
| 613 | return nil, err |
| 614 | } |
| 615 | if is, ok := stmt.(*ast.InsertStatement); ok { |
| 616 | if is.Pos.IsZero() { |
| 617 | is.Pos = stmtPos |
| 618 | } |
| 619 | } |
| 620 | return stmt, nil |
| 621 | case models.TokenTypeUpdate: |
| 622 | stmtPos := p.currentLocation() |
| 623 | p.advance() |
| 624 | stmt, err := p.parseUpdateStatement() |
| 625 | if err != nil { |
no test coverage detected