@@ -2546,6 +2546,36 @@ func (p *Parser) parseNamedTableReference() (*ast.NamedTableReference, error) {
25462546 }
25472547 ref .SchemaObject = son
25482548
2549+ // T-SQL supports two syntaxes for table hints:
2550+ // 1. Old-style: table_name (nolock) AS alias - hints before alias, no WITH
2551+ // 2. New-style: table_name AS alias WITH (hints) - alias before hints, WITH required
2552+
2553+ // Check for old-style hints (without WITH keyword): table (nolock) as alias
2554+ if p .curTok .Type == TokenLParen && p .peekIsTableHint () {
2555+ p .nextToken () // consume (
2556+ for p .curTok .Type != TokenRParen && p .curTok .Type != TokenEOF {
2557+ hint , err := p .parseTableHint ()
2558+ if err != nil {
2559+ return nil , err
2560+ }
2561+ if hint != nil {
2562+ ref .TableHints = append (ref .TableHints , hint )
2563+ }
2564+ if p .curTok .Type == TokenComma {
2565+ p .nextToken ()
2566+ } else if p .curTok .Type != TokenRParen {
2567+ // Check if the next token is a valid table hint (space-separated hints)
2568+ if p .isTableHintToken () {
2569+ continue // Continue parsing space-separated hints
2570+ }
2571+ break
2572+ }
2573+ }
2574+ if p .curTok .Type == TokenRParen {
2575+ p .nextToken ()
2576+ }
2577+ }
2578+
25492579 // Parse optional alias (AS alias or just alias)
25502580 if p .curTok .Type == TokenAs {
25512581 p .nextToken ()
@@ -2563,14 +2593,10 @@ func (p *Parser) parseNamedTableReference() (*ast.NamedTableReference, error) {
25632593 }
25642594 }
25652595
2566- // Parse optional table hints WITH (hint, hint, ...) or old-style (hint, hint, ... )
2596+ // Check for new-style hints (with WITH keyword): alias WITH (hints )
25672597 if p .curTok .Type == TokenWith && p .peekTok .Type == TokenLParen {
25682598 p .nextToken () // consume WITH
2569- }
2570- if p .curTok .Type == TokenLParen {
2571- // Check if this looks like hints (first token is a hint keyword)
2572- // Save position to peek
2573- if p .peekIsTableHint () {
2599+ if p .curTok .Type == TokenLParen && p .peekIsTableHint () {
25742600 p .nextToken () // consume (
25752601 for p .curTok .Type != TokenRParen && p .curTok .Type != TokenEOF {
25762602 hint , err := p .parseTableHint ()
@@ -2583,9 +2609,8 @@ func (p *Parser) parseNamedTableReference() (*ast.NamedTableReference, error) {
25832609 if p .curTok .Type == TokenComma {
25842610 p .nextToken ()
25852611 } else if p .curTok .Type != TokenRParen {
2586- // Check if the next token is a valid table hint (space-separated hints)
25872612 if p .isTableHintToken () {
2588- continue // Continue parsing space-separated hints
2613+ continue
25892614 }
25902615 break
25912616 }
@@ -2606,6 +2631,35 @@ func (p *Parser) parseNamedTableReferenceWithName(son *ast.SchemaObjectName) (*a
26062631 ForPath : false ,
26072632 }
26082633
2634+ // T-SQL supports two syntaxes for table hints:
2635+ // 1. Old-style: table_name (nolock) AS alias - hints before alias, no WITH
2636+ // 2. New-style: table_name AS alias WITH (hints) - alias before hints, WITH required
2637+
2638+ // Check for old-style hints (without WITH keyword): table (nolock) as alias
2639+ if p .curTok .Type == TokenLParen && p .peekIsTableHint () {
2640+ p .nextToken () // consume (
2641+ for p .curTok .Type != TokenRParen && p .curTok .Type != TokenEOF {
2642+ hint , err := p .parseTableHint ()
2643+ if err != nil {
2644+ return nil , err
2645+ }
2646+ if hint != nil {
2647+ ref .TableHints = append (ref .TableHints , hint )
2648+ }
2649+ if p .curTok .Type == TokenComma {
2650+ p .nextToken ()
2651+ } else if p .curTok .Type != TokenRParen {
2652+ if p .isTableHintToken () {
2653+ continue
2654+ }
2655+ break
2656+ }
2657+ }
2658+ if p .curTok .Type == TokenRParen {
2659+ p .nextToken ()
2660+ }
2661+ }
2662+
26092663 // Parse optional alias (AS alias or just alias)
26102664 if p .curTok .Type == TokenAs {
26112665 p .nextToken ()
@@ -2625,13 +2679,10 @@ func (p *Parser) parseNamedTableReferenceWithName(son *ast.SchemaObjectName) (*a
26252679 }
26262680 }
26272681
2628- // Parse optional table hints WITH (hint, hint, ...) or old-style (hint, hint, ... )
2682+ // Check for new-style hints (with WITH keyword): alias WITH (hints )
26292683 if p .curTok .Type == TokenWith && p .peekTok .Type == TokenLParen {
26302684 p .nextToken () // consume WITH
2631- }
2632- if p .curTok .Type == TokenLParen {
2633- // Check if this looks like hints (first token is a hint keyword)
2634- if p .peekIsTableHint () {
2685+ if p .curTok .Type == TokenLParen && p .peekIsTableHint () {
26352686 p .nextToken () // consume (
26362687 for p .curTok .Type != TokenRParen && p .curTok .Type != TokenEOF {
26372688 hint , err := p .parseTableHint ()
0 commit comments