parseTopClause parses SQL Server's TOP n [PERCENT] [WITH TIES] clause. Returns nil when the current dialect is not SQL Server or TOP is absent. Note: "TOP" is detected via a string comparison rather than a dedicated token-type constant because the lexer does not define a TokenTypeTOP - it tokenises
()
| 259 | // plain identifier/keyword literal. A future lexer enhancement could introduce |
| 260 | // models.TokenTypeTop and replace the strings.ToUpper check below. |
| 261 | func (p *Parser) parseTopClause() (*ast.TopClause, error) { |
| 262 | if p.dialect != string(keywords.DialectSQLServer) || strings.ToUpper(p.currentToken.Token.Value) != "TOP" { |
| 263 | return nil, nil |
| 264 | } |
| 265 | p.advance() // Consume TOP |
| 266 | |
| 267 | hasParen := p.isType(models.TokenTypeLParen) |
| 268 | if hasParen { |
| 269 | p.advance() // Consume ( |
| 270 | } |
| 271 | |
| 272 | countExpr, err := p.parsePrimaryExpression() |
| 273 | if err != nil { |
| 274 | return nil, fmt.Errorf("expected expression after TOP: %w", err) |
| 275 | } |
| 276 | |
| 277 | if hasParen { |
| 278 | if !p.isType(models.TokenTypeRightParen) { |
| 279 | return nil, p.expectedError(") after TOP expression") |
| 280 | } |
| 281 | p.advance() // Consume ) |
| 282 | } |
| 283 | |
| 284 | topClause := &ast.TopClause{Count: countExpr} |
| 285 | |
| 286 | // Optional PERCENT |
| 287 | if p.isType(models.TokenTypePercent) || |
| 288 | (p.currentToken.Token.Type == models.TokenTypeKeyword && strings.ToUpper(p.currentToken.Token.Value) == "PERCENT") { |
| 289 | topClause.IsPercent = true |
| 290 | p.advance() |
| 291 | } |
| 292 | |
| 293 | // Optional WITH TIES |
| 294 | if p.isType(models.TokenTypeWith) && p.peekToken().Token.Type == models.TokenTypeTies { |
| 295 | topClause.WithTies = true |
| 296 | p.advance() // Consume WITH |
| 297 | p.advance() // Consume TIES |
| 298 | |
| 299 | } |
| 300 | |
| 301 | return topClause, nil |
| 302 | } |
| 303 | |
| 304 | // parseSelectColumnList parses the comma-separated column/expression list in SELECT. |
| 305 | func (p *Parser) parseSelectColumnList() ([]ast.Expression, error) { |
no test coverage detected