parseSnowflakeStageStatement parses Snowflake stage operations as stubs: COPY INTO FROM [options] PUT file:// @ GET @ file:// LIST @ (or LS) REMOVE @ / The statement is consumed token-by-token (tracking balanced parens) until ';
(kind string)
| 779 | // ';' or EOF and returned as a DescribeStatement placeholder tagged with the |
| 780 | // operation kind. No AST modeling yet; follow-up work. |
| 781 | func (p *Parser) parseSnowflakeStageStatement(kind string) (ast.Statement, error) { |
| 782 | p.advance() // Consume leading kind token |
| 783 | |
| 784 | // COPY INTO: consume the INTO keyword if present. |
| 785 | if kind == "COPY" && p.isType(models.TokenTypeInto) { |
| 786 | p.advance() |
| 787 | } |
| 788 | |
| 789 | // Consume the rest of the statement body. |
| 790 | depth := 0 |
| 791 | for { |
| 792 | t := p.currentToken.Token.Type |
| 793 | if t == models.TokenTypeEOF { |
| 794 | break |
| 795 | } |
| 796 | if t == models.TokenTypeSemicolon && depth == 0 { |
| 797 | break |
| 798 | } |
| 799 | if t == models.TokenTypeLParen { |
| 800 | depth++ |
| 801 | } else if t == models.TokenTypeRParen { |
| 802 | depth-- |
| 803 | } |
| 804 | p.advance() |
| 805 | } |
| 806 | stub := ast.GetDescribeStatement() |
| 807 | stub.TableName = kind |
| 808 | return stub, nil |
| 809 | } |
| 810 | |
| 811 | // NewParser creates a new parser with optional configuration. |
| 812 | func NewParser(opts ...ParserOption) *Parser { |
no test coverage detected